第一次版本提交

This commit is contained in:
yeyang
2022-10-05 20:05:49 +08:00
parent 724d94a3f0
commit 10fcc358a6
87 changed files with 5699 additions and 0 deletions

1058
apps/各种通知.js Normal file

File diff suppressed because it is too large Load Diff

90
apps/名片点赞v3.js Normal file
View File

@@ -0,0 +1,90 @@
/*
* @作者: 超市椰羊(746659424)
* @介绍:
*/
import { segment } from "oicq"
//由于oicq不加好友点不上赞
/**没加好友回复 */
let notFriend = "不加好友不点🙄"
/** 点赞成功回复 n是点赞数 普通用户为 10svip 为 20*/
let success = "给你点了[n]下哦,记得回我~"
/** 点赞失败的回复(一般是点赞上限) */
let failds = "今天点过了,害搁这讨赞呐";
/**是否需要要回复的图片*/
let picture = true
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: '点赞插件',
/** 功能描述 */
dsc: '给自己资料卡点赞',
/** https://oicqjs.github.io/oicq/#events */
event: 'message',
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^(我要|给我)?(资料卡)?(点赞|赞我)$',
/** 执行方法 */
fnc: 'zan'
}
]
})
}
async zan(e) {
/**判断是否为好友 */
let isFriend = await Bot.fl.get(e.user_id)
if (!isFriend) return e.reply(notFriend, true)
/** 点赞成功回复的图片*/
let imgs = [
"https://xiaobai.klizi.cn/API/ce/zan.php?qq=",
"https://xiaobapi.top/api/xb/api/bixin.php?qq=",
"https://xiaobapi.top/api/xb/api/zan.php?qq="]
/** 一个随机数 */
let random = Math.floor(Math.random() * (imgs.length - 0))
let success_img = segment.image(imgs[random] + e.user_id)
/** 点赞失败的图片 */
let failds_img = segment.image(`https://xiaobai.klizi.cn/API/ce/paa.php?qq=${e.user_id}`)
/** 执行点赞*/
let n = 0;
while (true) {
let res = await Bot.sendLike(e.user_id, 10)
if (!res) {
break;
} else {
n += 10;
}
}
let success_ = success.replace(/\[n]/g, String(n))
let success_result = ""
let failds_result = ""
if (picture) {
success_result = ["\n", success_, success_img]
failds_result = ["\n", failds, failds_img]
} else {
success_result = "\b" + success_
failds_result = "\b" + failds
}
/**判断点赞是否成功*/
let msg = n > 0 ? success_result : failds_result
/**回复 */
e.reply(msg, false, { at: true })
return true
}
}

870
apps/小助手.js Normal file
View File

@@ -0,0 +1,870 @@
/*
* @作者: 超市椰羊(746659424)
* @介绍: 提供一些对机器人的远程操作 可使用 "助手帮助" 查看命令
*/
import plugin from '../../lib/plugins/plugin.js';
import { segment } from "oicq";
import fetch from 'node-fetch';
import cfg from '../../lib/config/config.js';
let Qzonedetermine;
let groupPhotoid;
export class example extends plugin {
constructor() {
super({
name: '小助手',
dsc: '远程对机器人进行一些操作',
event: 'message',
priority: 5000,
rule: [
{
reg: '^#?助手帮助$',
fnc: 'help'
},
{
reg: '^#?改头像.*$',
fnc: 'Photo'
},
{
reg: '^#?改昵称.*$',
fnc: 'Myname'
},
{
reg: '^#?改签名.*$',
fnc: 'Sign'
},
{
reg: '^#?改状态.*$',
fnc: 'State'
},
{
reg: '^#?发好友.*$',
fnc: 'Friends'
},
{
reg: '^#?发群聊.*$',
fnc: 'Groupmsg'
},
{
reg: '^#?退群.*$',
fnc: 'Quit'
},
{
reg: '^#?删好友.*$',
fnc: 'Deletes'
},
{
reg: '^#?改性别.*$',
fnc: 'Sex'
},
{
reg: '^#?取直链.*$',
fnc: 'Picture'
},
{
reg: '^#?取face.*$',
fnc: 'Face'
},
{
reg: '^#?查(Q|q)绑.*$',
fnc: 'Qbang'
},
{
reg: '^#?取说说列表.*$',
fnc: 'Qzonelist'
},
{
reg: '^#?删说说.*$',
fnc: 'Qzonedel'
},
{
reg: '^#?发说说.*$',
fnc: 'Qzonesay'
},
{
reg: '^#?(清空说说|清空留言)$',
fnc: 'QzoneEmpty'
},
{
reg: '^#?改群名片.*$',
fnc: 'MyGroupname'
},
{
reg: '^#?改群头像.*$',
fnc: 'GroupPhoto'
},
{
reg: '^#?改群昵称.*$',
fnc: 'Groupname'
},
{
reg: '^#?获取(群|好友)列表$',
fnc: 'Grouplist'
},
]
})
}
//帮助
async help(e) {
let msg = [
segment.image("https://api.ixiaowai.cn/api/api.php"),
"小助手 by 超市椰羊 \n",
"--------------------\n",
"#发群聊 <群号> <内容> \n",
"#发好友 <QQ> <内容> \n",
"#改头像 <图片> \n",
"#改状态 <状态> \n",
"#改昵称 <昵称> \n",
"#改签名 <签名> \n",
"#改性别 <性别> \n",
"#改群名片 <名片> \n",
"#改群昵称 <昵称> \n",
"#改群头像 <图片> \n",
"#删好友 <QQ> \n",
"#退群 <群号> \n",
"#获取群列表\n",
"#获取好友列表\n",
"#取说说列表 <页数> \n",
"#发说说 <内容> \n",
"#删说说 <序号>\n",
"#清空说说\n",
"#清空留言\n",
"#取直链 <图片>\n",
"#取face <face表情>",
"#查Q绑 <QQ>"
]
e.reply(msg);
}
/**改头像*/
async Photo(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
if (!e.img) {
this.setContext('Photos')
e.reply("✳️ 请发送图片");
return;
}
await Bot.setAvatar(e.img[0])
.then(() => { e.reply("✅ 头像修改成功") })
.catch((err) => {
e.reply("❎ 头像修改失败");
console.log(err);
})
}
async Photos() {
let img = this.e.img
if (this.e.msg === "取消") {
this.finish('Photos')
await this.reply('✅ 已取消')
return;
}
if (!img) {
this.setContext('Photos')
await this.reply('❎ 请发送图片或取消')
return;
}
await Bot.setAvatar(img[0])
.then(() => this.e.reply("✅ 头像修改成功"))
.catch((err) => {
this.e.reply("❎ 头像修改失败");
console.log(err)
})
this.finish('Photos')
}
/** 改昵称*/
async Myname(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let name = e.msg.replace(/#|改昵称/g, "").trim()
await Bot.setNickname(name)
.then(() => e.reply("✅ 昵称修改成功"))
.catch((err) => {
e.reply("❎ 昵称修改失败");
console.log(err);
})
}
/** 改群名片 */
async MyGroupname(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let group = '';
let card = '';
if (e.isPrivate) {
let msg = e.msg.split(" ")
group = msg[1].match(/[1-9]\d*/g);
card = msg.slice(2).join(" ");
if (!group) return e.reply("❎ 群号不能为空");
if (!Bot.gl.get(Number(msg[1]))) return e.reply("❎ 群聊列表查无此群");
} else {
group = e.group_id;
card = e.msg.replace(/#|改群名片/g, "").trim()
}
if (!card) return e.reply("❎ 名片不能为空");
Bot.pickGroup(group).setCard(cfg.qq, card)
.then(() => e.reply("✅ 群名片修改成功"))
.catch(err => {
e.reply("✅ 群名片修改失败")
console.log(err);
})
}
/**改群头像 */
async GroupPhoto(e) {
if (e.isPrivate) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
groupPhotoid = e.msg.replace(/#|改群头像/g, "").trim()
if (!groupPhotoid) return e.reply("❎ 群号不能为空");
if (!(/^\d+$/.test(groupPhotoid))) return e.reply("❎ 您的群号不合法");
if (!Bot.gl.get(Number(groupPhotoid))) return e.reply("❎ 群聊列表查无此群");
} else {
if (e.member.is_admin || e.member.is_owner) {
groupPhotoid = e.group_id
} else {
return e.reply(["哼~你不是管理员人家不听你的", segment.face(231)])
}
}
groupPhotoid = Number(groupPhotoid);
if (Bot.pickGroup(groupPhotoid).is_admin || Bot.pickGroup(groupPhotoid).is_owner) {
if (!e.img) {
this.setContext('picture')
e.reply("✳️ 请发送图片");
return;
}
Bot.pickGroup(groupPhotoid).setAvatar(e.img[0])
.then(() => e.reply("✅ 群头像修改成功"))
.catch((err) => {
e.reply("✅ 群头像修改失败")
console.log(err);
})
} else {
return e.reply("❎ 没有管理员人家做不到啦~>_<");
}
}
picture() {
let img = this.e.img
if (this.e.msg === "取消") {
this.finish('picture')
this.e.reply('✅ 已取消')
return;
}
if (!img) {
this.setContext('picture')
this.e.reply('❎ 请发送图片或取消')
return;
}
Bot.pickGroup(groupPhotoid).setAvatar(this.e.img[0])
.then(() => this.e.reply("✅ 群头像修改成功"))
.catch((err) => {
this.e.reply("✅ 群头像修改失败")
console.log(err);
})
this.finish('picture')
}
/**改群昵称 */
async Groupname(e) {
let group = '';
let card = '';
if (e.isPrivate) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let msg = e.msg.split(" ")
group = msg[1].match(/[1-9]\d*/g);
card = msg.slice(2).join(" ");
if (!group) return e.reply("❎ 群号不能为空");
if (!Bot.gl.get(Number(msg[1]))) return e.reply("❎ 群聊列表查无此群");
} else {
if (e.member.is_admin || e.member.is_owner) {
group = e.group_id
card = e.msg.replace(/#|改群昵称/g, "").trim()
} else {
return e.reply(["哼~你不是管理员人家不听你的", segment.face(231)])
}
}
if (!card) return e.reply("❎ 昵称不能为空");
group = Number(group);
if (Bot.pickGroup(group).is_admin || Bot.pickGroup(group).is_owner) {
Bot.pickGroup(group).setName(card)
.then(() => e.reply("✅ 群昵称修改成功"))
.catch(err => {
e.reply("✅ 群昵称修改失败")
console.log(err);
})
} else {
return e.reply("❎ 没有管理员人家做不到啦~>_<");
}
}
/** 改签名*/
async Sign(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let signs = e.msg.replace(/#|改签名/g, "").trim()
await Bot.setSignature(signs)
.then(() => e.reply("✅ 签名修改成功"))
.catch((err) => {
e.reply("❎ 签名修改失败");
console.log(err)
})
}
/** 改状态*/
async State(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let signs = e.msg.replace(/#|改状态/g, "").trim()
if (!signs) return e.reply("❎ 状态不为空可选值我在线上离开隐身忙碌Q我吧请勿打扰");
let res = {
"离开": 31,
"忙碌": 50,
"隐身": 41,
"Q我吧": 60,
"请勿打扰": 70,
"我在线上": 11,
}
let status = {
31: "离开",
50: "忙碌",
70: "请勿打扰",
41: "隐身",
11: "我在线上",
60: "Q我吧",
};
if (!(signs in res)) return e.reply("❎ 可选值我在线上离开隐身忙碌Q我吧请勿打扰")
await Bot.setOnlineStatus(res[signs])
.then(() => e.reply("✅ 在线状态修改成功"))
.then(() => e.reply(`✅ 现在的在线状态为【${status[Bot.status]}`))
.catch(err => {
e.reply("❎ 在线状态修改失败");
console.log(err);
})
return true;
}
/** 发好友*/
async Friends(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let msgs = e.message[0].text.split(" ")
if (msgs.length == 1 && !(/\d/.test(msgs[0]))) return e.reply("❎ QQ号不能为空");
let qq
if (/\d/.test(msgs[0])) {
qq = msgs[0].match(/[1-9]\d*/g)
e.message[0].text = msgs.slice(1).join(" ");
} else {
qq = msgs[1]
e.message[0].text = msgs.slice(2).join(" ");
}
if (!/^\d+$/.test(qq)) return e.reply("❎ QQ号不正确人家做不到的啦>_<~");
if (!Bot.fl.get(Number(qq))) return e.reply("❎ 好友列表查无此人");
if (!e.message[0].text) e.message.shift()
if (e.message.length === 0) return e.reply("❎ 消息不能为空");
await Bot.pickFriend(qq).sendMsg(e.message)
.then(() => e.reply("✅ 私聊消息已送达"))
.catch(err => e.reply(`❎ 发送失败\n错误信息为:${err.message}`))
}
/** 发群聊*/
async Groupmsg(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let msgs = e.message[0].text.split(" ")
e.message[0].text = msgs.slice(2).join(" ");
if (msgs.length < 2) return e.reply("❎ 您输入的指令不合法");
if (!/^\d+$/.test(msgs[1])) return e.reply("❎ 您输入的群号不合法");
if (!Bot.gl.get(Number(msgs[1]))) return e.reply("❎ 群聊列表查无此群");
if (!e.message[0].text) e.message.shift()
if (e.message.length === 0) return e.reply("❎ 消息不能为空");
await Bot.pickGroup(msgs[1]).sendMsg(e.message)
.then(() => e.reply("✅ 群聊消息已送达"))
.catch((err) => e.reply(`❎ 发送失败\n错误信息为:${err.message}`))
}
/**退群 */
async Quit(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let quits = e.msg.replace(/#|退群/g, "").trim()
if (!quits) return e.reply("❎ 群号不能为空");
if (!/^\d+$/.test(quits)) return e.reply("❎ 群号不合法");
if (!Bot.gl.get(Number(quits))) return e.reply("❎ 群聊列表查无此群")
await Bot.pickGroup(quits).quit()
.then(() => e.reply(`✅ 已退出群聊`))
.catch((err) => {
e.reply("❎ 退出失败");
console.log(err)
})
}
/**删好友 */
async Deletes(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true)
let quits = e.msg.replace(/#|删好友/g, "").trim()
if (e.message[1]) {
quits = e.message[1].qq
} else {
quits = quits.match(/[1-9]\d*/g)
}
if (!quits) return e.reply("❎ 请输入正确的QQ号")
if (!Bot.fl.get(Number(quits))) return e.reply("❎ 好友列表查无此人");
await Bot.pickFriend(quits).delete()
.then(() => e.reply(`✅ 已删除好友`))
.catch((err) => {
e.reply("❎ 删除失败");
console.log(err);
})
}
/**改性别 */
async Sex(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let sex = e.msg.replace(/#|改性别/g, "").trim();
if (!sex) return e.reply("❎ 性别不能为空 可选值:男,女,无\n改为无为无性别");
let res = {
"无": 0,
"男": 1,
"女": 2,
}
if (!(sex in res)) return e.reply("❎ 可选值:男,女,无(改为无,为无性别)");
await Bot.setGender(res[sex])
.then(() => e.reply(`✅ 已修改性别`))
.catch((err) => {
e.reply("❎ 修改失败");
console.log(err);
})
}
/**取直链 */
async Picture(e) {
if (!e.img) {
this.setContext('imgs')
await this.reply('✳️ 请发送图片')
return;
}
await e.reply(`✅ 检测到${e.img.length}张图片`)
for (let i of e.img) {
await e.reply([segment.image(i), "直链:", i])
}
}
async imgs() {
let img = this.e.img
if (this.e.msg === "取消") {
this.finish('imgs')
await this.reply('✅ 已取消')
return;
}
if (!img) {
this.setContext('imgs')
await this.reply('❎ 请发送图片或取消')
return;
}
await this.e.reply(img[0])
this.finish('imgs')
}
/** 取Face表情 */
async Face(e) {
let face = [];
for (let m of e.message) {
if (m.type === "face") {
let s = false;
for (let i of face) { if (i.id === m.id) s = true }
if (!s) face.push(m)
}
}
if (face.length === 0) return e.reply("❎ 表情参数不可为空", true);
let res = face.map(function (item) {
return [
`表情:`,
item,
`\nid${item.id}`,
`\n描述:${item.text}`
]
})
for (let i of res) {
await e.reply(i)
}
}
/** 查Q绑 */
async Qbang(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let qq = e.message[0].text.replace(/#|查(Q|q)绑/g, "").trim()
if (e.message[1]) {
qq = e.message[1].qq
} else {
qq = qq.match(/[1-9]\d*/g)
}
if (!qq) return e.reply("❎ 请输入正确的QQ号")
let qbang = await fetch(`https://zy.xywlapi.cc/qqapi?qq=${qq}`).then(res => res.json()).catch(err => console.log(err))
let lol = await fetch(`https://api.xywlapi.cc/qqlol?qq=${qq}`).then(res => res.json()).catch(err => console.log(err))
if (!qbang) return e.reply("❎ 接口查询失败");
if (qbang.status != 200) {
try {
e.reply(`❎ 错误信息:${qbang.message}`)
} catch {
e.reply(`❎ 此QQ号无法查询`)
}
return false;
}
let wb = await fetch(`https://api.xywlapi.cc/wbphone?phone=${qbang.phone}`).then(res => res.json()).catch(err => console.log(err))
let msg = [
`🐧:${qbang.qq}\n`,
`📱:${qbang.phone}\n`,
`🌏:${qbang.phonediqu}`
]
try {
if (lol.status == 200) {
msg.push(`\nLOL${lol.name}(${lol.daqu})`)
}
} catch {
console.log(`LOL没有找到`);
}
try {
if (wb.status == 200) {
msg.push(`\n微博uid${wb.id}`)
}
} catch {
console.log(`微博没有找到`);
}
let timeout = 600000; //0表示不撤回单位毫秒
let msgRes = await e.reply(msg);
if (timeout != 0 && msgRes && msgRes.message_id) {
let target = null;
if (e.isGroup) {
target = e.group;
} else {
target = e.friend;
}
if (target != null) {
setTimeout(() => {
target.recallMsg(msgRes.message_id);
target.recallMsg(e.message_id);
}, timeout);
}
}
return true;
}
/**QQ空间 说说列表*/
async Qzonelist(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let res = e.message[0].text.replace(/#|取说说列表/g, "").trim()
if (!res) res = 1
if (!parseInt(res)) return e.reply(`❎ 请检查页数是否正确`)
let list = await getlist()
list = list.msglist
if (!list) return e.reply(`❎ 说说列表为空`)
let msg = [
"✅ 获取成功,说说列表如下:\n"
]
let page = 5 * (res - 1)
for (let i = 0 + page; i < 5 + page; i++) {
if (!list[i]) break
let arr = `${i + 1}.${getLimit(list[i].content)}\n- [${list[i].secret ? "私密" : "公开"}] | ${formatDate(list[i].created_time)} | ${list[i].commentlist ? list[i].commentlist.length : 0}条评论\n`
msg.push(arr)
}
if (res > Math.ceil(list.length / 5)) return e.reply(`❎ 页数超过最大值`)
msg.push(`页数:[${res}/${Math.ceil(list.length / 5)}]`)
e.reply(msg)
}
/** 删除说说 */
async Qzonedel(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let res = e.message[0].text.replace(/#|删说说/g, "").trim()
if (!res) return e.reply(`❎ 序号不可为空`)
res = res.match(/\d/)
if (!res) return e.reply(`❎ 请检查序号是否正确`)
let list = await getlist()
if (!list.msglist) return e.reply(`❎ 说说列表为空`)
let ck = getck()
if ((res - 1) >= list.msglist.length) return e.reply(`❎ 序号超过最大值`)
let something = list.msglist[res - 1]
let url = `https://xiaobai.klizi.cn/API/qqgn/ss_delete.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&tid=${something.tid}`
let result = await fetch(url).then(res => res.text()).catch(err => console.log(err))
if (!result) return e.reply(`❎ 接口请求失败`)
if (/删除说说成功/.test(result)) {
e.reply(`✅ 删除说说成功:\n ${res}.${getLimit(something.content)} \n - [${something.secret ? "私密" : "公开"}] | ${formatDate(something.created_time)} | ${something.commentlist ? something.commentlist.length : 0} 条评论`)
} else if (/删除失败/.test(result)) {
e.reply(`❎ 删除失败`)
}
}
/** 发说说 */
async Qzonesay(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let res = e.message[0].text.replace(/#|发说说/g, "").trim()
let ck = getck()
let url;
if (e.img) {
url = `https://xiaobai.klizi.cn/API/qqgn/ss_sendimg.php?uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&url=${e.img[0]}&msg=${res}`
} else {
url = `http://xiaobai.klizi.cn/API/qqgn/ss_send.php?data=json&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&msg=${res}`
}
let result = await fetch(url).then(res => res.json()).catch(err => console.log(err))
let msg = [`✅ 说说发表成功,内容:\n`, getLimit(result.content)]
if (result.code != 0) return e.reply(`❎ 说说发表失败\n错误信息:${result.message}`)
if (result.pic) {
msg.push(segment.image(result.pic[0].url1))
}
msg.push(`\n- [${result.secret ? "私密" : "公开"}] | ${formatDate(result.t1_ntime)}`)
e.reply(msg)
}
/** 清空说说和留言*/
async QzoneEmpty(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
if (/清空说说/.test(e.msg)) {
this.setContext('QzonedelAll')
e.reply("✳️ 即将删除全部说说请发送:\n" + "------确认清空或取消------");
Qzonedetermine = true;
return true;
} else if (/清空留言/.test(e.msg)) {
this.setContext('QzonedelAll')
e.reply("✳️ 即将删除全部留言请发送:\n" + "------确认清空或取消------");
Qzonedetermine = false
return true;
}
}
async QzonedelAll() {
let msg = this.e.msg
if (msg == "确认清空") {
this.finish('QzonedelAll')
let ck = getck()
let url
if (Qzonedetermine) {
url = `https://xiaobai.klizi.cn/API/qqgn/ss_empty.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}`
} else {
url = `https://xiaobai.klizi.cn/API/qqgn/qzone_emptymsgb.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}`
}
let result = await fetch(url).then(res => res.text()).catch(err => console.log(err))
this.e.reply(`${result}`)
return true;
} else if (msg == "取消") {
this.finish('QzonedelAll')
this.e.reply("✅ 已取消")
return false;
} else {
this.setContext('QzonedelAll')
this.e.reply("❎ 请输入:确认清空或取消")
return false;
}
}
//获取群|好友列表
async Grouplist(e) {
if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true);
let listMap;
let message = [];
let list = []
let yes = false
if (/群列表/.test(e.msg)) {
//获取群列表并转换为数组
listMap = Array.from(Bot.gl.values())
//添加有几个群
message.push(`群列表如下,共${listMap.length}个群`)
//遍历添加
listMap.forEach((item, index) => {
list.push(`${index + 1}${item.group_name}(${item.group_id})\n`)
})
yes = true
} else if (/好友列表/.test(e.msg)) {
//获取好友列表并转换为数组
listMap = Array.from(Bot.fl.values())
//添加有多少个好友
message.push(`好友列表如下,共${listMap.length}个好友`)
//遍历添加
listMap.forEach((item, index) => {
list.push(`${index + 1}${item.nickname}(${item.user_id})\n`)
})
}
//去除最后一个的换行符
list[list.length - 1] = list[list.length - 1].replace(/\n/, "")
message.push(list)
if (yes) {
message.push("可使用 #退群123456789 来退出某群")
} else {
message.push("可使用 #删好友123456789 来删除某人")
}
//制作转发消息
let forwardMsg = []
for (let i of message) {
forwardMsg.push(
{
message: i,
nickname: Bot.nickname,
user_id: Bot.uin
}
)
}
if (e.isGroup) {
forwardMsg = await e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await e.friend.makeForwardMsg(forwardMsg)
}
//发送消息
e.reply(forwardMsg)
}
}
/**字数限制 */
function getLimit(str) {
let s = str.slice(0, 10)
return str.length > 10 ? s + "..." : str
}
/**时间格式化 */
function formatDate(time) {
var now = new Date(parseFloat(time) * 1000);
var month = now.getMonth() + 1;
var date = now.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (date >= 0 && date <= 9) {
date = "0" + date;
}
var hour = now.getHours();
var minute = now.getMinutes();
if (hour >= 1 && hour <= 9) {
hour = "0" + hour;
}
if (minute >= 0 && minute <= 9) {
minute = "0" + minute;
}
return month + "/" + date + " " + hour + ":" + minute
}
/**取说说列表*/
async function getlist() {
let ck = getck()
let url = `https://xiaobai.klizi.cn/API/qqgn/ss_list.php?data=json&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&qq=${cfg.qq}`
let list = await fetch(url).then(res => res.json()).catch(err => console.log(err))
if (!list) {
return e.reply("❎ 取说说列表失败")
} else {
return list
}
}
/**取cookies */
function getck() {
let cookie = Bot.cookies['qzone.qq.com']
let ck = cookie.replace(/=/g, `":"`).replace(/;/g, `","`).replace(/ /g, "").trim()
ck = ck.substring(0, ck.length - 2)
ck = `{"`.concat(ck).concat("}")
return JSON.parse(ck)
}

80
apps/百变头像v3.js Normal file
View File

@@ -0,0 +1,80 @@
import fs from 'fs'
import fetch from 'node-fetch';
/**
* 在“resources”文件夹下 新建“头像”文件夹把要修改的头像扔进去
* 随机修改一个头像文件夹里面的头像,默认每五分钟修改一次
*/
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: '头像',
/** 功能描述 */
dsc: '定时随机修改头像',
/** https://oicqjs.github.io/oicq/#events */
event: 'message',
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^#?换头像$',
/** 执行方法 */
fnc: 'avatar'
}]
})
/** 定时任务 */
this.task = {
/**Cron表达式 每五分钟执行一次 */
cron: '0 */10 * * * ?',
name: '定时随机修改头像',
fnc: () => this.avatar()
}
}
async avatar() {
//项目路径
let _path = process.cwd();
//头像路径
let paths = `${_path}/resources/头像`
let data;
let random;
try {
//获取头像文件夹下的文件
data = fs.readdirSync("././././resources/头像")
//随机数
random = Math.floor(Math.random() * (data.length - 0)) + 0;
} catch { console.log("无头像文件夹"); }
let url;
if (Math.random() > 0.5) {
url = await fetch("https://api.uomg.com/api/rand.avatar?sort=动漫女&format=json").then(res => res.json()).then(res => res.imgurl).catch(err => console.log(err))
} else {
url = "http://api.btstu.cn/sjtx/api.php?lx=c2&format=images"
}
//修改头像
try {
Bot.setAvatar(url).then(() => { logger.mark("[头像]修改网络头像") }).catch(
err => {
logger.error("[头像]API失效")
console.log(err);
}
)
} catch {
Bot.setAvatar(`file:///${paths}/${data[random]}`).then(() => { logger.mark("[头像]修改本地头像") }).catch(
err => {
logger.error("[头像]本地头像报错")
console.log(err);
}
)
}
}
}

70
apps/百变气泡v3.js Normal file
View File

@@ -0,0 +1,70 @@
import plugin from "../../lib/plugins/plugin.js";
import fetch from 'node-fetch'
import cfg from '../../lib/config/config.js'
import common from '../../lib/common/common.js'
//设置会员参数 (普通、vip、svip)
const member = "svip"
const myck = {
"code": 0,
"uin": "746659424",
"skey": "@qPj9eqrJZ",
"gtk": "1674138517",
"pt4token": "s4xN*kb8Bf-7rWDdbtkWVRj-xg5LL3ydX4t7jC6NLTM_",
"pskey": "YAfPtfubqFp4-4K0j3KWqb-B-O07H9tpX7eESL30zsw_",
"superkey": "vLB8ZIs8Pr*r-zdlZcBYzas5l9fU2ExoG7LQko3d0QQ_",
"state": "登录成功!",
"name": "超市椰羊"
}
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: "百变气泡",
/** 功能描述 */
dsc: "百变气泡",
/** https://oicqjs.github.io/oicq/#events */
event: "message",
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: "^换气泡$",
/** 执行方法 */
fnc: "Changeable",
},
],
});
/** 定时任务默认每10分钟一次不建议太短 */
this.task = {
cron: '0 */10 * * * ?',
name: '百变气泡',
fnc: () => this.Changeable()
}
}
async Changeable() {
//获取ck
let cookie = Bot.cookies['vip.qq.com']
let ck = cookie.replace(/=/g, `":"`).replace(/;/g, `","`).replace(/ /g, "").trim()
ck = ck.substring(0, ck.length - 2)
ck = `{"`.concat(ck).concat("}")
ck = JSON.parse(ck)
let url = `http://www.dreamling.xyz/API/QQ/multivariant_bubbles/api.php?uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&type=text&member=${member}`
let result = await fetch(url).then(res => res.text())
let myurl = `http://www.dreamling.xyz/API/QQ/multivariant_bubbles/api.php?uin=${myck.uin}&skey=${myck.skey}&pskey=${myck.pskey}&type=text&member=${member}`
let my = await fetch(myurl).then(res => res.text()).catch(common.relpyPrivate(746659424, "ck失效"))
logger.mark(`[百变气泡] ${result}`)
logger.mark(`[百变气泡自己] ${my}`)
}
}

200
apps/角色收益曲线.js Normal file
View File

@@ -0,0 +1,200 @@
import plugin from '../../lib/plugins/plugin.js'
import gsCfg from '../genshin/model/gsCfg.js'
import { segment } from 'oicq'
import fs from 'node:fs'
import common from '../../lib/common/common.js'
export class curve extends plugin {
constructor() {
super({
name: 'nga收益曲线',
dsc: '收益曲线',
event: 'message',
priority: 500,
rule: [
{
reg: '^#*(.*)收益曲线(帮助)?$',
fnc: 'curve'
},
]
})
this.path = './resources/收益曲线'
}
//初始化
async init() {
if (!fs.existsSync(this.path)) {
fs.mkdirSync(this.path)
}
}
async curve() {
let role = {}
if (/#?收益曲线帮助/.test(this.e.msg)) role.name = "帮助"
else role = gsCfg.getRole(this.e.msg, '收益曲线')
if (!role) return
/** 主角特殊处理 */
if (['10000005', '10000007', '20000000'].includes(String(role.roleId))) {
if (!['风主', '岩主', '雷主', '草主'].includes(role.alias)) {
await this.e.reply('请选择:风主收益曲线、岩主收益曲线、雷主收益曲线、草主收益曲线')
return
} else {
role.name = role.alias
}
}
if (!image[role.name]) return this.e.reply("暂时无该角色收益曲线~>_<")
this.imgPath = `${this.path}/${role.name}.png`
if (!fs.existsSync(this.imgPath)) {
await this.getImg(role.name)
}
if (fs.existsSync(this.imgPath)) {
await this.e.reply(segment.image(this.imgPath));
return true;
}
}
//下载图片
async getImg(name) {
logger.mark(`${this.e.logFnc} 下载${name}素材图`)
if (!await common.downFile(image[name], this.imgPath)) {
return false
}
logger.mark(`${this.e.logFnc} 下载${name}素材成功`)
return true
}
}
const image = {
"帮助": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-j5voXxZ96T3cS1di-q9.png",
"烟绯": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-gz71XxZ96T3cS1di-q9.png",
"辛炎": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-1uboXyZ9cT3cS1di-q9.png",
"霄宫": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-acsfXyZ9eT3cS1di-q9.png",
"香菱": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-akwxXwZ8wT3cS1di-q9.png",
"托马": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-in5cXwZ90T3cS1di-q9.png",
"胡桃": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-6vbsXvZ8pT3cS1di-q9.png",
"迪卢克": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-dgbbXxZ92T3cS1di-q9.png",
"安柏": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-8m6vXxZ91T3cS1di-q9.png",
"夜兰": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-3oq4XxZ95T3cS1di-q9.png",
"行秋": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-b18cXwZ91T3cS1di-q9.png",
"神里绫人": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-hyagXyZ9fT3cS1di-q9.png",
"珊瑚宫心海": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-3ktjXxZ9bT3cS1di-q9.png",
"莫娜": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-9cifXyZ9bT3cS1di-q9.png",
"达达利亚": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-hu24XyZ9cT3cS1di-q9.png",
"芭芭拉": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-1t4oXxZ95T3cS1di-q9.png",
"可莉": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-bplpXwZ8zT3cS1di-q9.png",
"班尼特": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-i6w3XwZ8xT3cS1di-q9.png",
"重云": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-al2oXxZ9bT3cS1di-q9.png",
"优菈": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-ec2aXxZ98T3cS1di-q9.png",
"神里凌华": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-jurwXxZ97T3cS1di-q9.png",
"申鹤": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-2mawXxZ9bT3cS1di-q9.png",
"七七": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-gbmkXxZ99T3cS1di-q9.png",
"罗莎莉亚": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-2tppXyZ9cT3cS1di-q9.png",
"凯亚": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-cpsdXxZ96T3cS1di-q9.png",
"甘雨": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-jh27XxZ96T3cS1di-q9.png",
"迪奥娜": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-4pvvXxZ97T3cS1di-q9.png",
"埃洛伊": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-a90bXwZ8yT3cS1di-q9.png",
"钟离": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-3ifiXwZ8zT3cS1di-q9.png",
"云堇": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-9yzvXxZ97T3cS1di-q9.png",
"五郎": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-j6rfXxZ9aT3cS1di-q9.png",
"诺艾尔": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-9ht1XxZ97T3cS1di-q9.png",
"凝光": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-3sa1XxZ94T3cS1di-q9.png",
"岩主": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-kje0XxZ92T3cS1di-q9.png",
"荒泷一斗": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-73zhXxZ97T3cS1di-q9.png",
"阿贝多": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-cwmhXwZ8wT3cS1di-q9.png",
"早柚": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-28j7XxZ94T3cS1di-q9.png",
"魈": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-htbXwZ8yT3cS1di-q9.png",
"琴": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-kqstXxZ9aT3cS1di-q9.png",
"鹿野院平藏": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-jx1yXxZ92T3cS1di-q9.png",
"雷主": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-aqakXxZ93T3cS1di-q9.png",
"雷泽": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-axdiXxZ97T3cS1di-q9.png",
"雷电将军": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-dagnXyZ9cT3cS1di-q9.png",
"九条裟罗": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-ep0dXwZ8yT3cS1di-q9.png",
"提娜里": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-1twzXwZ8uT3cS1di-q9.png",
"草主": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-620hXuZ8aT3cS1di-q9.png",
"枫原万叶": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-i5niXvZ8iT3cS1di-q9.png",
"丽莎": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-ba0sXxZ96T3cS1di-q9.png",
"刻晴": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-j403XyZ9hT3cS1di-q9.png",
"九歧忍": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-1zzuXxZ97T3cS1di-q9.png",
"菲谢尔": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-77grXxZ98T3cS1di-q9.png",
"北斗": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-5xbkZ2dT3cS1di-q9.png",
"八重神子": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-ddaeXyZ9kT3cS1di-q9.png",
"多莉": "https://img.nga.178.com/attachments/mon_202209/09/i2Q181-45azXyZ9bT3cS1di-q9.png",
"柯莱": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-86c8XvZ8pT3cS1di-q9.png",
"温迪": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-2s69XwZ8uT3cS1di-q9.png",
"砂糖": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-95mbXwZ8vT3cS1di-q9.png",
"风主": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-bplhXvZ8lT3cS1di-q9.png"
}

51
apps/随机唱鸭v3.js Normal file
View File

@@ -0,0 +1,51 @@
import plugin from '../../lib/plugins/plugin.js'
import fetch from 'node-fetch'
import { segment } from "oicq";
export class example extends plugin {
constructor() {
super({
/** 功能名称 */
name: '随机唱鸭',
/** 功能描述 */
dsc: '随机唱鸭',
/** https://oicqjs.github.io/oicq/#events */
event: 'message',
/** 优先级,数字越小等级越高 */
priority: 5000,
rule: [
{
/** 命令正则匹配 */
reg: '^唱歌$',
/** 执行方法 */
fnc: 'Sing'
}
]
})
}
async Sing(e) {
let url = "https://xiaobai.klizi.cn/API/music/changya.php"
let res = await fetch(url).catch(err => console.log(err))
if (!res) {
e.reply("❎ 接口请求失败")
return false;
}
res = await res.json()
if (res.code != 200) {
e.reply("❎ 接口请求错误")
return false;
}
let data = res.data
await e.reply(segment.record(data.audioSrc))
//处理歌词
let lyric = data.lyrics.map(function (item) {
return `${item}\n`
})
lyric[lyric.length - 1] = data.lyrics[data.lyrics.length - 1]
await e.reply(lyric)
return true;
}
}

45
components/Cfg.js Normal file
View File

@@ -0,0 +1,45 @@
import fs from 'fs'
import lodash from 'lodash'
const _path = process.cwd()
const _cfgPath = `${_path}/plugins/xiaofei-plugin/components/`
let cfg = {}
try {
if (fs.existsSync(_cfgPath + 'cfg.json')) {
cfg = JSON.parse(fs.readFileSync(_cfgPath + 'cfg.json', 'utf8')) || {}
}
} catch (e) {
// do nth
}
let Cfg = {
get (rote, def = '') {
return lodash.get(cfg, rote, def)
},
set (rote, val) {
lodash.set(cfg, rote, val)
fs.writeFileSync(_cfgPath + 'cfg.json', JSON.stringify(cfg, null, '\t'))
},
del (rote) {
lodash.set(cfg, rote, undefined)
fs.writeFileSync(_cfgPath + 'cfg.json', JSON.stringify(cfg, null, '\t'))
},
scale (pct = 1) {
let scale = Cfg.get('sys.scale', 100)
scale = Math.min(2, Math.max(0.5, scale / 100))
pct = pct * scale
return `style=transform:scale(${pct})`
},
isDisable (e, rote) {
if (Cfg.get(rote, true)) {
return false
}
if (/^#*小飞/.test(e.msg || '')) {
return false
}
return true
}
}
export default Cfg

13
components/Common.js Normal file
View File

@@ -0,0 +1,13 @@
import Cfg from './Cfg.js'
import render from './common-lib/render.js'
function sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
export default {
render,
cfg: Cfg.get,
isDisable: Cfg.isDisable,
sleep
}

107
components/Config.js Normal file
View File

@@ -0,0 +1,107 @@
import YAML from 'yaml'
import chokidar from 'chokidar'
import fs from 'node:fs'
const Path = process.cwd();
const Plugin_Name = 'xiaofei-plugin'
const Plugin_Path = `${Path}/plugins/${Plugin_Name}`;
class Config {
constructor () {
this.config = {}
/** 监听文件 */
this.watcher = {}
this.ignore = []
}
/**
* @param app 功能
* @param name 配置文件名称
*/
getdefSet (app, name) {
return this.getYaml(app, name, 'defSet')
}
/** 用户配置 */
getConfig (app, name) {
return this.getYaml(app, name, 'config')
}
/**
* 获取配置yaml
* @param app 功能
* @param name 名称
* @param type 默认跑配置-defSet用户配置-config
*/
getYaml (app, name, type) {
let file = this.getFilePath(app, name, type)
let key = `${app}.${name}`
if (this.config[type][key]) return this.config[type][key]
try {
this.config[type][key] = YAML.parse(
fs.readFileSync(file, 'utf8')
)
} catch (error) {
logger.error(`[${app}][${name}] 格式错误 ${error}`)
return false
}
this.watch(file, app, name, type)
return this[type][key]
}
getFilePath (app, name, type) {
if(!this.config[type]){
this.config[type] = {};
}
if(!this.watcher[type]){
this.watcher[type] = {};
}
let config_path = `${Plugin_Path}/${type}/`;
let file = `${config_path}${app}.${name}.yaml`;
try{
if(!fs.existsSync(file)){
let default_file = `${config_path}default/${app}.${name}.yaml`;
fs.copyFileSync(default_file,file);
}
}catch(err){}
return file;
}
/** 监听配置文件 */
watch (file, app, name, type = 'defSet') {
let key = `${app}.${name}`
if (this.watcher[type][key]) return
const watcher = chokidar.watch(file)
watcher.on('change', path => {
delete this[type][key]
logger.mark(`[修改配置文件][${type}][${app}][${name}]`)
if (this[`change_${app}${name}`]) {
this[`change_${app}${name}`]()
}
})
this.watcher[type][key] = watcher
}
save (app, name, type) {
let file = this.getFilePath(app, name, type)
if (lodash.isEmpty(data)) {
fs.existsSync(file) && fs.unlinkSync(file)
} else {
let yaml = YAML.stringify(data)
fs.writeFileSync(file, yaml, 'utf8')
}
}
}
export default new Config()

224
components/Data.js Normal file
View File

@@ -0,0 +1,224 @@
import lodash from 'lodash'
import fs from 'fs'
const _path = process.cwd()
const plugin = 'xiaofei-plugin'
const getRoot = (root = '') => {
if (root === 'root' || root === 'yunzai') {
root = `${_path}/`
} else if (!root) {
root = `${_path}/plugins/${plugin}/`
}
return root
}
let Data = {
/*
* 根据指定的path依次检查与创建目录
* */
createDir (path = '', root = '', includeFile = false) {
root = getRoot(root)
let pathList = path.split('/')
let nowPath = root
pathList.forEach((name, idx) => {
name = name.trim()
if (!includeFile && idx <= pathList.length - 1) {
nowPath += name + '/'
if (name) {
if (!fs.existsSync(nowPath)) {
fs.mkdirSync(nowPath)
}
}
}
})
},
/*
* 读取json
* */
readJSON (file = '', root = '') {
root = getRoot(root)
if (fs.existsSync(`${root}/${file}`)) {
try {
return JSON.parse(fs.readFileSync(`${root}/${file}`, 'utf8'))
} catch (e) {
console.log(e)
}
}
return {}
},
/*
* 写JSON
* */
writeJSON (file, data, space = '\t', root = '') {
// 检查并创建目录
Data.createDir(file, root, true)
root = getRoot(root)
delete data._res
return fs.writeFileSync(`${root}/${file}`, JSON.stringify(data, null, space))
},
async getCacheJSON (key) {
try {
let txt = await redis.get(key)
if (txt) {
return JSON.parse(txt)
}
} catch (e) {
console.log(e)
}
return {}
},
async setCacheJSON (key, data, EX = 3600 * 24 * 90) {
await redis.set(key, JSON.stringify(data), { EX })
},
async importModule (file, root = '') {
root = getRoot(root)
if (!/\.js$/.test(file)) {
file = file + '.js'
}
if (fs.existsSync(`${root}/${file}`)) {
try {
let data = await import(`file://${root}/${file}?t=${new Date() * 1}`)
return data || {}
} catch (e) {
console.log(e)
}
}
return {}
},
async importDefault (file, root) {
let ret = await Data.importModule(file, root)
return ret.default || {}
},
async import (name) {
return await Data.importModule(`components/optional-lib/${name}.js`)
},
async importCfg (key) {
let sysCfg = await Data.importModule(`config/system/${key}_system.js`)
let diyCfg = await Data.importModule(`config/${key}.js`)
if (diyCfg.isSys) {
console.error(`miao-plugin: config/${key}.js无效已忽略`)
console.error(`如需配置请复制config/${key}_default.js为config/${key}.js请勿复制config/system下的系统文件`)
diyCfg = {}
}
return {
sysCfg,
diyCfg
}
},
/*
* 返回一个从 target 中选中的属性的对象
*
* keyList : 获取字段列表,逗号分割字符串
* key1, key2, toKey1:fromKey1, toKey2:fromObj.key
*
* defaultData: 当某个字段为空时会选取defaultData的对应内容
* toKeyPrefix返回数据的字段前缀默认为空。defaultData中的键值无需包含toKeyPrefix
*
* */
getData (target, keyList = '', cfg = {}) {
target = target || {}
let defaultData = cfg.defaultData || {}
let ret = {}
// 分割逗号
if (typeof (keyList) === 'string') {
keyList = keyList.split(',')
}
lodash.forEach(keyList, (keyCfg) => {
// 处理通过:指定 toKey & fromKey
let _keyCfg = keyCfg.split(':')
let keyTo = _keyCfg[0].trim()
let keyFrom = (_keyCfg[1] || _keyCfg[0]).trim()
let keyRet = keyTo
if (cfg.lowerFirstKey) {
keyRet = lodash.lowerFirst(keyRet)
}
if (cfg.keyPrefix) {
keyRet = cfg.keyPrefix + keyRet
}
// 通过Data.getVal获取数据
ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg)
})
return ret
},
getVal (target, keyFrom, defaultValue) {
return lodash.get(target, keyFrom, defaultValue)
},
// 异步池,聚合请求
async asyncPool (poolLimit, array, iteratorFn) {
const ret = [] // 存储所有的异步任务
const executing = [] // 存储正在执行的异步任务
for (const item of array) {
// 调用iteratorFn函数创建异步任务
const p = Promise.resolve().then(() => iteratorFn(item, array))
// 保存新的异步任务
ret.push(p)
// 当poolLimit值小于或等于总任务个数时进行并发控制
if (poolLimit <= array.length) {
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
executing.push(e) // 保存正在执行的异步任务
if (executing.length >= poolLimit) {
// 等待较快的任务执行完成
await Promise.race(executing)
}
}
}
return Promise.all(ret)
},
// sleep
sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
},
// 获取默认值
def () {
for (let idx in arguments) {
if (!lodash.isUndefined(arguments[idx])) {
return arguments[idx]
}
}
},
// 循环字符串回调
eachStr: (arr, fn) => {
if (lodash.isString(arr)) {
arr = arr.replace(/\s*(;||、|)\s*/, ',')
arr = arr.split(',')
} else if (lodash.isNumber(arr)) {
arr = [arr.toString()]
}
lodash.forEach(arr, (str, idx) => {
if (!lodash.isUndefined(str)) {
fn(str.trim ? str.trim() : str, idx)
}
})
},
regRet (reg, txt, idx) {
if (reg && txt) {
let ret = reg.exec(txt)
if (ret && ret[idx]) {
return ret[idx]
}
}
return false
}
}
export default Data

100
components/Version.js Normal file
View File

@@ -0,0 +1,100 @@
import fs from 'fs'
import lodash from 'lodash'
import cfg from '../../../lib/config/config.js'
const Plugin_Path = `${process.cwd()}/plugins/xiaofei-plugin`;
const README_path = `${Plugin_Path}/README.md`
const CHANGELOG_path = `${Plugin_Path}/CHANGELOG.md`
const yunzai_ver = `v${cfg.package.version}`;
let logs = {}
let changelogs = []
let currentVersion
let versionCount = 6
const getLine = function (line) {
line = line.replace(/(^\s*\*|\r)/g, '')
line = line.replace(/\s*`([^`]+`)/g, '<span class="cmd">$1')
line = line.replace(/`\s*/g, '</span>')
line = line.replace(/\s*\*\*([^\*]+\*\*)/g, '<span class="strong">$1')
line = line.replace(/\*\*\s*/g, '</span>')
line = line.replace(/ⁿᵉʷ/g, '<span class="new"></span>')
return line
}
try {
if (fs.existsSync(CHANGELOG_path)) {
logs = fs.readFileSync(CHANGELOG_path, 'utf8') || ''
logs = logs.replace(/\t/g,' ').split('\n')
let temp = {};
let lastLine = {}
lodash.forEach(logs, (line) => {
if (versionCount <= -1) {
return false
}
let versionRet = /^#\s*([0-9a-zA-Z\\.~\s]+?)\s*$/.exec(line.trim())
if (versionRet && versionRet[1]) {
let v = versionRet[1].trim()
if (!currentVersion) {
currentVersion = v
} else {
changelogs.push(temp)
if (/0\s*$/.test(v) && versionCount > 0) {
//versionCount = 0
versionCount--
} else {
versionCount--
}
}
temp = {
version: v,
logs: []
}
} else {
if (!line.trim()) {
return
}
if (/^\*/.test(line)) {
lastLine = {
title: getLine(line),
logs: []
}
if(!temp.logs){
temp = {
version: line,
logs: []
}
}
temp.logs.push(lastLine)
} else if (/^\s{2,}\*/.test(line)) {
lastLine.logs.push(getLine(line))
}
}
})
}
} catch (e) {
logger.error(e);
// do nth
}
try{
if(fs.existsSync(README_path)){
let README = fs.readFileSync(README_path, 'utf8') || ''
let reg = /版本:(.*)/.exec(README)
if(reg){
currentVersion = reg[1]
}
}
}catch(err){}
let Version = {
get ver () {
return currentVersion;
},
get yunzai(){
return yunzai_ver;
},
get logs(){
return changelogs;
}
}
export default Version

15
components/cfg.json Normal file
View File

@@ -0,0 +1,15 @@
{
"sys": {
"help": true,
"scale": 100
},
"char": {
"wife": false,
"char": true
},
"wiki": {
"abyss": true,
"wiki": false,
"stat": true
}
}

View File

@@ -0,0 +1,51 @@
import { Data, Version, Plugin_Name} from '../index.js'
import Cfg from '../Cfg.js'
import fs from 'fs'
import puppeteer from '../../../../lib/puppeteer/puppeteer.js'
const _path = process.cwd()
export default async function (path, params, cfg) {
let [app, tpl] = path.split('/')
let { e } = cfg
let layoutPath = process.cwd() + `/plugins/${Plugin_Name}/resources/common/layout/`
let resPath = `../../../../../plugins/${Plugin_Name}/resources/`
Data.createDir(`data/html/${Plugin_Name}/${app}/${tpl}`, 'root')
let data = {
...params,
_plugin: Plugin_Name,
saveId: params.saveId || params.save_id || tpl,
tplFile: `./plugins/${Plugin_Name}/resources/${app}/${tpl}.html`,
pluResPath: resPath,
_res_path: resPath,
_layout_path: layoutPath,
_tpl_path: process.cwd() + `/plugins/${Plugin_Name}/resources/common/tpl/`,
defaultLayout: layoutPath + 'default.html',
elemLayout: layoutPath + 'elem.html',
pageGotoParams: {
waitUntil: 'networkidle0'
},
sys: {
scale: Cfg.scale(cfg.scale || 1),
copyright: `Created By Yunzai-Bot<span class="version">${Version.yunzai}</span> & xiaofei-Plugin<span class="version">${Version.ver}</span>`
},
quality: 100
}
if (process.argv.includes('web-debug')) {
// debug下保存当前页面的渲染数据方便模板编写与调试
// 由于只用于调试开发者只关注自己当时开发的文件即可暂不考虑app及plugin的命名冲突
let saveDir = _path + '/data/ViewData/'
if (!fs.existsSync(saveDir)) {
fs.mkdirSync(saveDir)
}
let file = saveDir + tpl + '.json'
data._app = app
fs.writeFileSync(file, JSON.stringify(data))
}
let base64 = await puppeteer.screenshot(`${Plugin_Name}/${app}/${tpl}`, data)
let ret = true
if (base64) {
ret = await e.reply(base64)
}
return cfg.retMsgId ? ret : true
}

10
components/index.js Normal file
View File

@@ -0,0 +1,10 @@
const Path = process.cwd();
const Plugin_Name = 'xiaofei-plugin'
const Plugin_Path = `${Path}/plugins/${Plugin_Name}`;
import Version from './Version.js'
import Data from './Data.js'
import Cfg from './Cfg.js'
import Common from './Common.js'
import Config from './Config.js'
export { Cfg, Common, Config, Data, Version, Path, Plugin_Name, Plugin_Path}

View File

@@ -0,0 +1,3 @@
此目录为系统配置目录
请勿修改此目录下的文件,否则可能导致工作不正常
如需配置可配置上级目录复制对应_default.js 文件进行配置

42
index.js Normal file
View File

@@ -0,0 +1,42 @@
import fs from 'node:fs'
import common from '../../lib/common/common.js'
const files = fs.readdirSync('./plugins/suiyue/apps').filter(file => file.endsWith('.js'))
let ret = []
files.forEach((file) => {
ret.push(import(`./apps/${file}`))
})
ret = await Promise.allSettled(ret)
let apps = {}
for (let i in files) {
let name = files[i].replace('.js', '')
if (ret[i].status != 'fulfilled') {
logger.error(`载入插件错误:${logger.red(name)}`)
logger.error(ret[i].reason)
continue
}
apps[name] = ret[i].value[name]
}
logger.info('-----------')
logger.info('加载碎月插件完成..[v1.0.0]')
logger.info('-----------')
let restart = await redis.get(`Yunzai:suiyue:restart`);
if (restart) {
restart = JSON.parse(restart);
if (restart.isGroup) {
Bot.pickGroup(restart.id).sendMsg(`重启成功`);
} else {
common.relpyPrivate(restart.id, `重启成功`);
}
redis.del(`Yunzai:suiyue:restart`);
}
export { apps }

View File

@@ -0,0 +1,7 @@
.font-ys {
font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
}
.font-nzbz {
font-family: Number, "印品南征北战NZBZ体", NZBZ, PingFangSC-Medium, "PingFang SC", sans-serif;
}
/*# sourceMappingURL=base.css.map */

View File

@@ -0,0 +1,7 @@
.font-YS {
font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
}
.font-NZBZ {
font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

455
resources/common/common.css Normal file
View File

@@ -0,0 +1,455 @@
@font-face {
font-family: 'Number';
src: url("./font/tttgbnumber.woff") format('woff'), url("./font/tttgbnumber.ttf") format('truetype');
}
@font-face {
font-family: 'NZBZ';
src: url("./font/NZBZ.woff") format('woff'), url("./font/NZBZ.ttf") format('truetype');
}
@font-face {
font-family: 'YS';
src: url("./font/HYWH-65W.woff") format('woff'), url("./font/HYWH-65W.ttf") format('truetype');
}
.font-YS {
font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
}
.font-NZBZ {
font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-user-select: none;
user-select: none;
}
body {
font-size: 18px;
color: #1e1f20;
font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
transform: scale(1.4);
transform-origin: 0 0;
width: 600px;
}
.container {
width: 600px;
padding: 20px 15px 10px 15px;
background-size: contain;
}
.head-box {
border-radius: 15px;
padding: 10px 20px;
position: relative;
color: #fff;
margin-top: 30px;
}
.head-box .title {
font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
font-size: 36px;
text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, 0.9);
}
.head-box .title .label {
display: inline-block;
margin-left: 10px;
}
.head-box .genshin_logo {
position: absolute;
top: 1px;
right: 15px;
width: 97px;
}
.head-box .label {
font-size: 16px;
text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, 0.9);
}
.head-box .label span {
color: #d3bc8e;
padding: 0 2px;
}
.notice {
color: #888;
font-size: 12px;
text-align: right;
padding: 12px 5px 5px;
}
.notice-center {
color: #fff;
text-align: center;
margin-bottom: 10px;
text-shadow: 1px 1px 1px #333;
}
.copyright {
font-size: 14px;
text-align: center;
color: #fff;
position: relative;
padding-left: 10px;
text-shadow: 1px 1px 1px #000;
margin: 10px 0;
}
.copyright .version {
color: #d3bc8e;
display: inline-block;
padding: 0 3px;
}
/* */
.cons {
display: inline-block;
vertical-align: middle;
padding: 0 5px;
border-radius: 4px;
}
.cons-0 {
background: #666;
color: #fff;
}
.cons-n0 {
background: #404949;
color: #fff;
}
.cons-1 {
background: #5cbac2;
color: #fff;
}
.cons-2 {
background: #339d61;
color: #fff;
}
.cons-3 {
background: #3e95b9;
color: #fff;
}
.cons-4 {
background: #3955b7;
color: #fff;
}
.cons-5 {
background: #531ba9cf;
color: #fff;
}
.cons-6 {
background: #ff5722;
color: #fff;
}
.cons2-0 {
border-radius: 4px;
background: #666;
color: #fff;
}
.cons2-1 {
border-radius: 4px;
background: #71b1b7;
color: #fff;
}
.cons2-2 {
border-radius: 4px;
background: #369961;
color: #fff;
}
.cons2-3 {
border-radius: 4px;
background: #4596b9;
color: #fff;
}
.cons2-4 {
border-radius: 4px;
background: #4560b9;
color: #fff;
}
.cons2-5 {
border-radius: 4px;
background: #531ba9cf;
color: #fff;
}
.cons2-6 {
border-radius: 4px;
background: #ff5722;
color: #fff;
}
/******** Fetter ********/
.fetter {
width: 50px;
height: 50px;
display: inline-block;
background: url('./item/fetter.png');
background-size: auto 100%;
}
.fetter.fetter1 {
background-position: 0% 0;
}
.fetter.fetter2 {
background-position: 11.11111111% 0;
}
.fetter.fetter3 {
background-position: 22.22222222% 0;
}
.fetter.fetter4 {
background-position: 33.33333333% 0;
}
.fetter.fetter5 {
background-position: 44.44444444% 0;
}
.fetter.fetter6 {
background-position: 55.55555556% 0;
}
.fetter.fetter7 {
background-position: 66.66666667% 0;
}
.fetter.fetter8 {
background-position: 77.77777778% 0;
}
.fetter.fetter9 {
background-position: 88.88888889% 0;
}
.fetter.fetter10 {
background-position: 100% 0;
}
/******** ELEM ********/
.elem-hydro .talent-icon {
background-image: url("./bg/talent-hydro.png");
}
.elem-hydro .elem-bg,
.hydro-bg {
background-image: url("./bg/bg-hydro.jpg");
}
.elem-anemo .talent-icon {
background-image: url("./bg/talent-anemo.png");
}
.elem-anemo .elem-bg,
.anemo-bg {
background-image: url("./bg/bg-anemo.jpg");
}
.elem-cryo .talent-icon {
background-image: url("./bg/talent-cryo.png");
}
.elem-cryo .elem-bg,
.cryo-bg {
background-image: url("./bg/bg-cryo.jpg");
}
.elem-electro .talent-icon {
background-image: url("./bg/talent-electro.png");
}
.elem-electro .elem-bg,
.electro-bg {
background-image: url("./bg/bg-electro.jpg");
}
.elem-geo .talent-icon {
background-image: url("./bg/talent-geo.png");
}
.elem-geo .elem-bg,
.geo-bg {
background-image: url("./bg/bg-geo.jpg");
}
.elem-pyro .talent-icon {
background-image: url("./bg/talent-pyro.png");
}
.elem-pyro .elem-bg,
.pyro-bg {
background-image: url("./bg/bg-pyro.jpg");
}
.elem-dendro .talent-icon {
background-image: url("./bg/talent-dendro.png");
}
.elem-dendro .elem-bg,
.dendro-bg {
background-image: url("./bg/bg-dendro.jpg");
}
/* cont */
.cont {
border-radius: 10px;
background: url("../common/cont/card-bg.png") top left repeat-x;
background-size: auto 100%;
margin: 5px 15px 5px 10px;
position: relative;
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, 0.8);
overflow: hidden;
color: #fff;
font-size: 16px;
}
.cont-title {
background: rgba(0, 0, 0, 0.4);
box-shadow: 0 0 1px 0 #fff;
color: #d3bc8e;
padding: 10px 20px;
text-align: left;
border-radius: 10px 10px 0 0;
}
.cont-title span {
font-size: 12px;
color: #aaa;
margin-left: 10px;
font-weight: normal;
}
.cont-title.border-less {
background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
box-shadow: none;
padding-bottom: 5px;
}
.cont-body {
padding: 10px 15px;
font-size: 12px;
background: rgba(0, 0, 0, 0.5);
box-shadow: 0 0 1px 0 #fff;
font-weight: normal;
}
.cont-footer {
padding: 10px 15px;
font-size: 12px;
background: rgba(0, 0, 0, 0.5);
font-weight: normal;
}
.cont > ul.cont-msg {
display: block;
padding: 5px 10px;
background: rgba(0, 0, 0, 0.5);
}
ul.cont-msg,
.cont-footer ul {
padding-left: 15px;
}
ul.cont-msg li,
.cont-footer ul li {
margin: 5px 0;
margin-left: 15px;
}
ul.cont-msg li strong,
.cont-footer ul li strong {
font-weight: normal;
margin: 0 2px;
color: #d3bc8e;
}
.cont-table {
display: table;
width: 100%;
}
.cont-table .tr {
display: table-row;
}
.cont-table .tr:nth-child(even) {
background: rgba(0, 0, 0, 0.4);
}
.cont-table .tr:nth-child(odd) {
background: rgba(50, 50, 50, 0.4);
}
.cont-table .tr > div,
.cont-table .tr > td {
display: table-cell;
box-shadow: 0 0 1px 0 #fff;
}
.cont-table .tr > div.value-full {
display: table;
width: 200%;
}
.cont-table .tr > div.value-none {
box-shadow: none;
}
.cont-table .thead {
text-align: center;
}
.cont-table .thead > div,
.cont-table .thead > td {
color: #d3bc8e;
background: rgba(0, 0, 0, 0.4);
line-height: 40px;
height: 40px;
}
.cont-table .title,
.cont-table .th {
color: #d3bc8e;
padding-right: 15px;
text-align: right;
background: rgba(0, 0, 0, 0.4);
min-width: 100px;
vertical-align: middle;
}
.logo {
font-size: 18px;
text-align: center;
color: #fff;
margin: 20px 0 10px 0;
}
/* item-icon */
.item-icon {
width: 100%;
height: 100%;
border-radius: 4px;
position: relative;
overflow: hidden;
}
.item-icon .img {
width: 100%;
height: 100%;
display: block;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.item-icon.artis .img {
width: 84%;
height: 84%;
margin: 8%;
}
.item-icon.star1 {
background-image: url("../common/item/bg1.png");
}
.item-icon.opacity-bg.star1 {
background-image: url("../common/item/bg1-o.png");
}
.item-icon.star2 {
background-image: url("../common/item/bg2.png");
}
.item-icon.opacity-bg.star2 {
background-image: url("../common/item/bg2-o.png");
}
.item-icon.star3 {
background-image: url("../common/item/bg3.png");
}
.item-icon.opacity-bg.star3 {
background-image: url("../common/item/bg3-o.png");
}
.item-icon.star4 {
background-image: url("../common/item/bg4.png");
}
.item-icon.opacity-bg.star4 {
background-image: url("../common/item/bg4-o.png");
}
.item-icon.star5 {
background-image: url("../common/item/bg5.png");
}
.item-icon.opacity-bg.star5 {
background-image: url("../common/item/bg5-o.png");
}
.item-list {
display: flex;
}
.item-list .item-card {
width: 70px;
background: #e7e5d9;
}
.item-list .item-icon {
border-bottom-left-radius: 0;
border-bottom-right-radius: 12px;
}
.item-list .item-title {
color: #222;
font-size: 13px;
text-align: center;
padding: 2px;
white-space: nowrap;
overflow: hidden;
}
.item-list .item-icon {
height: initial;
}
.item-list .item-badge {
position: absolute;
display: block;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.6);
font-size: 12px;
color: #fff;
padding: 4px 5px 3px;
border-radius: 0 0 6px 0;
}
/*# sourceMappingURL=common.css.map */

View File

@@ -0,0 +1,390 @@
.font(@name, @file) {
@font-face {
font-family: @name;
src: url("./font/@{file}.woff") format('woff'), url("./font/@{file}.ttf") format('truetype');
}
}
.font('Number', 'tttgbnumber');
.font('NZBZ', 'NZBZ');
.font('YS', 'HYWH-65W');
@import "base.less";
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-user-select: none;
user-select: none;
}
body {
font-size: 18px;
color: #1e1f20;
font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif;
transform: scale(1.4);
transform-origin: 0 0;
width: 600px;
}
.container {
width: 600px;
padding: 20px 15px 10px 15px;
background-size: contain;
}
.head-box {
border-radius: 15px;
padding: 10px 20px;
position: relative;
color: #fff;
margin-top: 30px;
.title {
.font-NZBZ;
font-size: 36px;
text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, .9);
.label {
display: inline-block;
margin-left: 10px;
}
}
.genshin_logo {
position: absolute;
top: 1px;
right: 15px;
width: 97px;
}
.label {
font-size: 16px;
text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, .9);
span {
color: #d3bc8e;
padding: 0 2px;
}
}
}
.notice {
color: #888;
font-size: 12px;
text-align: right;
padding: 12px 5px 5px;
}
.notice-center {
color: #fff;
text-align: center;
margin-bottom: 10px;
text-shadow: 1px 1px 1px #333;
}
.copyright {
font-size: 14px;
text-align: center;
color: #fff;
position: relative;
padding-left: 10px;
text-shadow: 1px 1px 1px #000;
margin: 10px 0;
.version {
color: #d3bc8e;
display: inline-block;
padding: 0 3px;
}
}
/* */
.cons {
display: inline-block;
vertical-align: middle;
padding: 0 5px;
border-radius: 4px;
}
.cons(@idx, @bg, @color:#fff) {
.cons-@{idx} {
background: @bg;
color: @color;
}
}
.cons(0, #666);
.cons(n0, #404949);
.cons(1, #5cbac2);
.cons(2, #339d61);
.cons(3, #3e95b9);
.cons(4, #3955b7);
.cons(5, #531ba9cf);
.cons(6, #ff5722);
.cons2(@idx, @bg, @color:#fff) {
.cons2-@{idx} {
border-radius: 4px;
background: @bg;
color: @color;
}
}
.cons2(0, #666);
.cons2(1, #71b1b7);
.cons2(2, #369961);
.cons2(3, #4596b9);
.cons2(4, #4560b9);
.cons2(5, #531ba9cf);
.cons2(6, #ff5722);
/******** Fetter ********/
.fetter {
width: 50px;
height: 50px;
display: inline-block;
background: url('./item/fetter.png');
background-size: auto 100%;
@fetters: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
each(@fetters, {
&.fetter@{value} {
background-position: (-100%/9)+(100%/9)*@value 0;
}
})
}
/******** ELEM ********/
@elems: hydro, anemo, cryo, electro, geo, pyro, dendro;
each(@elems, {
.elem-@{value} .talent-icon {
background-image: url("./bg/talent-@{value}.png");
}
.elem-@{value} .elem-bg,
.@{value}-bg {
background-image: url("./bg/bg-@{value}.jpg");
}
})
/* cont */
.cont {
border-radius: 10px;
background: url("../common/cont/card-bg.png") top left repeat-x;
background-size: auto 100%;
// backdrop-filter: blur(3px);
margin: 5px 15px 5px 10px;
position: relative;
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, .8);
overflow: hidden;
color: #fff;
font-size: 16px;
}
.cont-title {
background: rgba(0, 0, 0, .4);
box-shadow: 0 0 1px 0 #fff;
color: #d3bc8e;
padding: 10px 20px;
text-align: left;
border-radius: 10px 10px 0 0;
span {
font-size: 12px;
color: #aaa;
margin-left: 10px;
font-weight: normal;
}
&.border-less {
background: linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));
box-shadow: none;
padding-bottom: 5px;
}
}
.cont-body {
padding: 10px 15px;
font-size: 12px;
background: rgba(0, 0, 0, 0.5);
box-shadow: 0 0 1px 0 #fff;
font-weight: normal;
}
.cont-footer {
padding: 10px 15px;
font-size: 12px;
background: rgba(0, 0, 0, 0.5);
font-weight: normal;
}
.cont > ul.cont-msg {
display: block;
padding: 5px 10px;
background: rgba(0, 0, 0, 0.5);
}
ul.cont-msg, .cont-footer ul {
padding-left: 15px;
li {
margin: 5px 0;
margin-left: 15px;
strong {
font-weight: normal;
margin: 0 2px;
color: #d3bc8e;
}
}
}
.cont-table {
display: table;
width: 100%;
}
.cont-table .tr {
display: table-row;
}
.cont-table .tr:nth-child(even) {
background: rgba(0, 0, 0, .4);
}
.cont-table .tr:nth-child(odd) {
background: rgba(50, 50, 50, .4);
}
.cont-table .tr > div,
.cont-table .tr > td {
display: table-cell;
box-shadow: 0 0 1px 0 #fff;
}
.cont-table .tr > div.value-full {
display: table;
width: 200%;
}
.cont-table .tr > div.value-none {
box-shadow: none;
}
.cont-table .thead {
text-align: center;
}
.cont-table .thead > div,
.cont-table .thead > td {
color: #d3bc8e;
background: rgba(0, 0, 0, .4);
line-height: 40px;
height: 40px;
}
.cont-table .title,
.cont-table .th {
color: #d3bc8e;
padding-right: 15px;
text-align: right;
background: rgba(0, 0, 0, .4);
min-width: 100px;
vertical-align: middle;
}
.logo {
font-size: 18px;
text-align: center;
color: #fff;
margin: 20px 0 10px 0;
}
/* item-icon */
.item-icon {
width: 100%;
height: 100%;
border-radius: 4px;
position: relative;
overflow: hidden;
.img {
width: 100%;
height: 100%;
display: block;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
&.artis {
.img {
width: 84%;
height: 84%;
margin: 8%;
}
}
@stars: 1, 2, 3, 4, 5;
each(@stars, {
&.star@{value} {
background-image: url("../common/item/bg@{value}.png");
}
&.opacity-bg.star@{value} {
background-image: url("../common/item/bg@{value}-o.png");
}
})
}
.item-list {
display: flex;
.item-card {
width: 70px;
background: #e7e5d9;
}
.item-icon {
border-bottom-left-radius: 0;
border-bottom-right-radius: 12px;
}
.item-title {
color: #222;
font-size: 13px;
text-align: center;
padding: 2px;
white-space: nowrap;
overflow: hidden;
}
.item-icon {
height: initial;
}
.item-badge {
position: absolute;
display: block;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.6);
font-size: 12px;
color: #fff;
padding: 4px 5px 3px;
border-radius: 0 0 6px 0;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="shortcut icon" href="#"/>
<link rel="preload" href="{{_res_path}}common/font/HYWH-65W.woff" as="font" type="font/woff">
<link rel="preload" href="{{_res_path}}common/font/NZBZ.woff" as="font" type="font/woff">
<link rel="preload" href="{{_res_path}}common/font/tttgbnumber.woff" as="font" type="font/woff">
<link rel="stylesheet" type="text/css" href="{{_res_path}}common/common.css"/>
<title>miao-plugin</title>
{{block 'css'}}
{{/block}}
</head>
<body class="elem-{{element||elem||`hydro`}} {{displayMode || mode || `default`}}-mode {{bodyClass}}" {{sys.scale}}>
<div class="container" id="container">
{{block 'main'}}{{/block}}
<div class="copyright">{{@sys.copyright}}</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link rel="shortcut icon" href="#"/>
<link rel="preload" href="{{_res_path}}common/font/HYWH-65W.woff" as="font" type="font/woff">
<link rel="preload" href="{{_res_path}}common/font/NZBZ.woff" as="font" type="font/woff">
<link rel="preload" href="{{_res_path}}common/font/tttgbnumber.woff" as="font" type="font/woff">
<link rel="stylesheet" type="text/css" href="{{_res_path}}common/common.css"/>
<title>miao-plugin</title>
{{block 'css'}}
{{/block}}
</head>
<body class="elem-{{element||elem||`hydro`}} {{displayMode || mode || `default`}}-mode {{bodyClass}}" {{sys.scale}}>
<div class="container elem-bg" id="container">
{{block 'main'}}{{/block}}
<div class="copyright">{{@sys.copyright}}</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 KiB

332
resources/common/tpl.css Normal file
View File

@@ -0,0 +1,332 @@
.item-card {
width: 66px;
margin: 4px;
position: relative;
border-radius: 5px;
}
.item-card .badge {
overflow: hidden;
border-radius: 50%;
display: block;
width: 26px;
height: 26px;
position: absolute;
right: -4px;
top: -4px;
background: #e9e5dc;
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.8), 2px 2px 2px rgba(50, 50, 50, 0.5);
z-index: 10;
}
.item-card .badge img {
width: 140%;
left: -27%;
top: -45%;
overflow: hidden;
background-size: 100%;
background-repeat: no-repeat;
position: absolute;
}
.item-card .item-bg {
width: 100%;
padding: 100% 0 0;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
margin: 0;
}
.item-card .bg1 {
background-image: url("./item/bg1.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg-1 {
background-image: url("./item/bg1.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg2 {
background-image: url("./item/bg2.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg-2 {
background-image: url("./item/bg2.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg3 {
background-image: url("./item/bg3.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg-3 {
background-image: url("./item/bg3.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg4 {
background-image: url("./item/bg4.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg-4 {
background-image: url("./item/bg4.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg5 {
background-image: url("./item/bg5.png");
border-radius: 5px 5px 15px 0;
}
.item-card .bg-5 {
background-image: url("./item/bg5.png");
border-radius: 5px 5px 15px 0;
}
.item-card .box {
border-radius: 5px;
overflow: hidden;
background: #e9e5dc;
}
.item-card .box .item-desc {
display: block;
font-weight: 500;
text-align: center;
bottom: 0;
background: #e9e5dc;
width: 100%;
font-size: 12px;
line-height: 16px;
white-space: nowrap;
overflow: hidden;
padding: 0 3px;
}
.item-card .box .item-desc:last-child {
padding-bottom: 2px;
}
.item-card .box .name {
overflow: hidden;
white-space: nowrap;
margin-top: 5px;
font-weight: 500;
text-align: center;
font-size: 14px;
}
.item-card .box .item-img {
width: 100%;
overflow: hidden;
background-size: 100%;
background-repeat: no-repeat;
position: absolute;
top: 0;
}
.item-card .item-life {
position: absolute;
top: 0;
left: 0;
z-index: 9;
font-size: 13px;
text-align: center;
color: #fff;
padding: 1px 4px;
border-radius: 3px;
}
.item-card .life1 {
background-color: #62a8ea;
}
.item-card .life2 {
background-color: #62a8ea;
}
.item-card .life3 {
background-color: #62a8ea;
}
.item-card .life4 {
background-color: #ff5722;
}
.item-card .life5 {
background-color: #ff5722;
}
.avatar-card {
margin: 3px;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8);
font-size: 13px;
}
.avatar-card .card {
border-radius: 7px;
box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3);
position: relative;
overflow: hidden;
background: #e7e5d9;
width: 70px;
}
.avatar-card .avatar-face {
width: 70px;
height: 70px;
border-radius: 7px 7px 15px 0;
background-size: 100% 100%;
background-repeat: no-repeat;
position: relative;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5);
}
.avatar-card .avatar-face .img {
background-position: center bottom;
}
.avatar-card .avatar-face .avatar-level {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
left: 0;
padding: 2px 5px 2px 3px;
border-radius: 0 4px 0 0;
color: #fff;
}
.avatar-card .cons {
border-radius: 0 0 0 5px;
padding: 2px 5px;
position: absolute;
right: 0;
top: 0;
}
.avatar-card .avatar-talent {
height: 21px;
padding: 3px 5px 2px;
font-size: 12px;
width: 100%;
color: #222;
text-align: center;
display: flex;
}
.avatar-card .avatar-talent .talent-item {
width: 20px;
height: 16px;
line-height: 17px;
margin: 0 2px;
text-align: center;
display: block;
background-size: contain;
opacity: 0.8;
position: relative;
border-radius: 3px;
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5);
}
.avatar-card .avatar-talent .talent-item.talent-plus {
font-weight: bold;
color: #0284b9;
}
.avatar-card .avatar-talent .talent-item.talent-crown {
background: #d3bc8e;
color: #3a2702;
box-shadow: 0 0 2px 0 #000;
}
.avatar-card .avatar-talent.no-talent {
font-size: 12px;
color: rgba(100, 100, 100, 0.5);
text-align: center;
padding: 3px 0 2px;
}
.avatar-card .avatar-talent.no-talent span {
transform: scale(0.75);
white-space: nowrap;
margin-left: -1px;
}
.avatar-card.card-mini .wide,
.avatar-card.card-mini .line {
display: none;
}
.avatar-card .avatar-name {
padding: 8px 0 0 5px;
color: #333;
}
.avatar-card .avatar-name strong {
font-size: 14px;
display: block;
height: 23px;
line-height: 20px;
}
.avatar-card .avatar-name .cons {
position: initial;
border-radius: 4px;
padding: 1px 3px;
vertical-align: baseline;
}
.avatar-card.card-wide .mini {
display: none;
}
.avatar-card.card-wide .card {
width: 146px;
display: flex;
}
.avatar-card.card-wide .avatar-face {
height: 126px;
width: 76px;
border-radius: 7px 0 0 7px;
}
.avatar-card.card-wide .img {
background-size: 100% auto;
background-position: 0 10%;
height: 135px;
margin-top: -9px;
}
.avatar-card.card-wide .avatar-info {
width: 70px;
}
.avatar-card.card-wide .line {
display: block;
height: 1px;
width: 100%;
margin: 5px 0;
background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(100, 100, 100, 0.5) 20%, rgba(100, 100, 100, 0.5) 80%, rgba(0, 0, 0, 0));
transform: scale(0.8);
}
.avatar-card.wide2 .card {
width: 298px;
}
.avatar-card.wide2 .avatar-face {
width: 146px;
}
.avatar-card.wide2 .avatar-face .img {
margin-top: -50px;
height: 176px;
}
.avatar-card.wide2 .avatar-info {
width: 146px;
padding-left: 5px;
}
.avatar-detail {
display: flex;
padding: 0 1px 2px;
}
.avatar-detail .item {
width: 31px;
height: 31px;
border-radius: 4px;
margin: 1px;
}
.avatar-weapon .icon {
border-radius: 4px;
}
.avatar-weapon .cons {
top: initial;
bottom: 0;
padding: 1px 3px;
border-radius: 3px 0 0 0;
}
.avatar-artis {
position: relative;
}
.avatar-artis .artis {
background: rgba(0, 0, 0, 0.5);
}
.avatar-artis.artis2 .img {
position: absolute;
transform: scale(0.7);
width: 92%;
height: 92%;
margin: 4%;
}
.avatar-artis.artis2 .img:first-child {
transform-origin: left top;
}
.avatar-artis.artis2 .img:last-child {
transform-origin: right bottom;
}
.item-list {
display: flex;
flex-wrap: wrap;
transform-origin: 0 0;
}
.item-list .item {
width: 65px;
}
/*# sourceMappingURL=tpl.css.map */

12
resources/common/tpl.less Normal file
View File

@@ -0,0 +1,12 @@
@import url('tpl/item-card');
@import url('tpl/avatar-card');
.item-list {
display: flex;
flex-wrap: wrap;
transform-origin: 0 0;
}
.item-list .item {
width: 65px;
}

View File

@@ -0,0 +1,116 @@
.arti-detail {
width: 185px;
border-radius: 10px;
background: url("../cont/card-bg.png") top left repeat-x;
background-size: auto 100%;
margin: 5px;
position: relative;
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, 0.8);
height: 205px;
overflow: hidden;
}
.arti-detail .arti-icon {
width: 60px;
height: 60px;
position: absolute;
left: 2px;
top: 3px;
}
.arti-detail .arti-icon span {
position: absolute;
right: 2px;
bottom: 0;
margin-left: 5px;
background: rgba(0, 0, 0, 0.5);
border-radius: 5px;
height: 18px;
line-height: 18px;
padding: 0 3px;
color: #fff;
font-size: 12px;
display: block;
}
.arti-detail .arti-icon img {
width: 60px;
height: 60px;
}
.arti-detail .head {
color: #fff;
padding: 12px 0 8px 68px;
}
.arti-detail .head strong {
font-size: 15px;
display: block;
white-space: nowrap;
overflow: hidden;
font-font: YS;
}
.arti-detail .head span {
font-size: 14px;
}
.arti-detail .head .mark {
font-family: Number, YS;
}
.arti-detail ul.detail {
width: 100%;
padding: 0;
position: initial;
font-family: YS;
}
.arti-detail ul.detail li {
padding: 0 3px;
font-size: 14px;
position: initial;
width: 100%;
display: table;
line-height: 26px;
height: 26px;
}
.arti-detail ul.detail li.nouse span {
color: #888;
}
.arti-detail ul.detail li.arti-main {
font-size: 16px;
padding: 3px 3px;
font-weight: bold;
}
.arti-detail ul.detail li span {
position: initial;
display: table-cell;
color: #fff;
font-family: YS;
}
.arti-detail ul.detail li.title {
text-align: left;
padding-left: 10px;
}
.arti-detail ul.detail li.val {
text-align: right;
padding-right: 10px;
font-family: Number;
}
.arti-detail ul.detail:nth-child(even) {
background: rgba(0, 0, 0, 0.4);
}
.arti-detail ul.detail:nth-child(odd) {
background: rgba(50, 50, 50, 0.4);
}
.arti-detail .avatar {
position: absolute;
left: 32px;
top: 26px;
width: 38px;
height: 38px;
border-radius: 50%;
overflow: hidden;
z-index: 3;
}
.arti-detail .avatar img {
max-width: 100%;
max-height: 100%;
}
.arti-detail .arti-icon img {
width: 52px;
height: 52px;
}
/*# sourceMappingURL=artis-detail.less.map */

View File

@@ -0,0 +1,57 @@
.avatar-card {
margin: 0 0 10px 10px;
border-radius: 7px;
box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3);
height: 88px;
position: relative;
overflow: hidden;
background: #e7e5d9;
}
.avatar-card img {
width: 70px;
height: 70px;
border-radius: 7px 7px 20px 0;
}
.avatar-card.star5 img {
background-image: url(../common/item/bg5.png);
width: 100%;
height: 70px;
/*filter: brightness(1.1);*/
background-size: 100%;
background-repeat: no-repeat;
}
.avatar-card.star4 img {
width: 100%;
height: 70px;
background-image: url(../common/item/bg4.png);
background-size: 100%;
background-repeat: no-repeat;
}
.avatar-card .num {
position: absolute;
top: 0;
right: 0;
z-index: 9;
font-size: 18px;
text-align: center;
color: #fff;
padding: 1px 5px;
border-radius: 4px;
background: rgba(0, 0, 0, 0.5);
}
.avatar-card .name,
.avatar-card .num_name {
position: absolute;
top: 70px;
left: 0;
z-index: 9;
font-size: 12px;
text-align: center;
width: 100%;
height: 16px;
line-height: 18px;
}
.avatar-card .num_name {
font-size: 16px;
}
/*# sourceMappingURL=avatar-card.css.map */

View File

@@ -0,0 +1,53 @@
{{set avatar = $data[0] || false }}
{{set {_res_path, cardType} = $data[1]}}
{{set weapon = avatar.weapon || {} }}
{{set talentMap = ['a','e','q'] }}
<div class="avatar-card elem-{{avatar.elem}} avatar-{{avatar.name}} card-{{cardType||'mini'}}">
<div class="card">
{{if avatar}}
<div class="avatar-face item-icon star{{avatar.star==4?4:5}}">
<div class="img mini" style="background-image:url({{_res_path}}{{avatar.face}})"></div>
<div class="img wide avatar-{{avatar.name}}" style="background-image:url({{_res_path}}{{avatar.gacha}})"></div>
<span class="cons cons-{{avatar.cons}} mini">{{avatar.cons}}</span>
<div class="avatar-level">Lv{{avatar.level}}</div>
</div>
<div class="avatar-info">
{{set talent = avatar.talent || {} }}
{{if talent.a && talent.a.level }}
<div class="avatar-name wide">
<strong>{{avatar.abbr}}</strong>
<span class="cons cons-{{avatar.cons}}">{{avatar.cons}}</span>
<span class="avatar-level">Lv{{avatar.level}}</span>
<div class="line"></div>
</div>
<div class="avatar-talent">
{{each talentMap k}}
{{set t = talent[k] || {} }} <span
class="talent-item talent-{{k}} talent-{{t.original===10?'crown':'none'}} talent-{{t.level>t.original?'plus':'none'}}">{{t.level}}</span>
{{/each}}
</div>
{{else}}
<div class="avatar-talent no-talent"><span>暂无天赋数据</span></div>
{{/if}}
<div class="line"></div>
<div class="avatar-detail">
<div class="item avatar-weapon">
<div class="item-icon star{{weapon.star}}">
<span class="img" style="background-image:url({{_res_path}}{{weapon.img}})"></span>
<span class="cons cons-{{weapon.affix}}">{{weapon.affix}}</span>
</div>
</div>
<div class="item avatar-artis artis{{avatar.artisSet?.names?.length}}">
<div class="artis item-icon">
{{each avatar.artisSet?.imgs img}}
<div class="img" style="background-image:url({{_res_path}}{{img}})"></div>
{{/each}}
</div>
<div class="item-info wide"></div>
</div>
</div>
{{/if}}
</div>
</div>
</div>

View File

@@ -0,0 +1,237 @@
.avatar-card {
margin: 3px;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8);
font-size: 13px;
.card {
border-radius: 7px;
box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%);
position: relative;
overflow: hidden;
background: #e7e5d9;
width: 70px;
}
.avatar-face {
width: 70px;
height: 70px;
border-radius: 7px 7px 15px 0;
background-size: 100% 100%;
background-repeat: no-repeat;
position: relative;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, .5);
.img {
background-position: center bottom;
}
.avatar-level {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
left: 0;
padding: 2px 5px 2px 3px;
border-radius: 0 4px 0 0;
color: #fff;
}
}
.cons {
border-radius: 0 0 0 5px;
padding: 2px 5px;
position: absolute;
right: 0;
top: 0;
}
.avatar-talent {
height: 21px;
padding: 3px 5px 2px;
font-size: 12px;
width: 100%;
color: #222;
text-align: center;
display: flex;
.talent-item {
width: 20px;
height: 16px;
line-height: 17px;
margin: 0 2px;
text-align: center;
display: block;
background-size: contain;
opacity: 0.8;
position: relative;
border-radius: 3px;
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5);
&.talent-plus {
font-weight: bold;
color: #0284b9;
}
&.talent-crown {
background: #d3bc8e;
color: #3a2702;
box-shadow: 0 0 2px 0 #000;
}
}
&.no-talent {
font-size: 12px;
color: rgba(100, 100, 100, .5);
text-align: center;
padding: 3px 0 2px;
span {
transform: scale(.75);
white-space: nowrap;
margin-left: -1px;
}
}
}
&.card-mini {
.wide, .line {
display: none;
}
}
.avatar-name {
padding: 8px 0 0 5px;
color: #333;
strong {
font-size: 14px;
display: block;
height: 23px;
line-height: 20px;
}
.cons {
position: initial;
border-radius: 4px;
padding: 1px 3px;
vertical-align: baseline;
}
}
&.card-wide {
.mini {
display: none;
}
.card {
width: 146px;
display: flex;
}
.avatar-face {
height: 126px;
width: 76px;
border-radius: 7px 0 0 7px;
}
.img {
background-size: 100% auto;
background-position: 0 10%;
height: 135px;
margin-top: -9px;
}
.avatar-info {
width: 70px;
}
.line {
display: block;
height: 1px;
width: 100%;
margin: 5px 0;
background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(100, 100, 100, .5) 20%, rgba(100, 100, 100, .5) 80%, rgba(0, 0, 0, 0));
transform: scale(.8)
}
}
&.wide2 {
.card {
width: 298px;
}
.avatar-face {
width: 146px;
.img {
margin-top: -50px;
height: 176px;
}
}
.avatar-info {
width: 146px;
padding-left: 5px;
}
}
}
.avatar-detail {
display: flex;
padding: 0 1px 2px;
.item {
width: 31px;
height: 31px;
border-radius: 4px;
margin: 1px;
}
}
.avatar-weapon {
.icon {
border-radius: 4px;
}
.cons {
top: initial;
bottom: 0;
padding: 1px 3px;
border-radius: 3px 0 0 0;
}
}
.avatar-artis {
position: relative;
.artis {
background: rgba(0, 0, 0, 0.5)
}
&.artis2 {
.img {
position: absolute;
transform: scale(.7);
width: 92%;
height: 92%;
margin: 4%;
&:first-child {
transform-origin: left top;
}
&:last-child {
transform-origin: right bottom;
}
}
}
}

View File

@@ -0,0 +1,204 @@
.profile {
position: relative;
margin-bottom: 10px;
}
.profile:after {
content: "";
display: block;
position: absolute;
left: 8px;
top: 115px;
bottom: 0;
right: 8px;
box-shadow: 0 0 2px 0 #fff;
border-radius: 5px;
z-index: 1;
}
.profile .main-pic {
width: 800px;
height: 500px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
margin-left: -260px;
position: relative;
z-index: 2;
}
.profile .detail {
position: absolute;
right: 20px;
top: 20px;
color: #fff;
z-index: 3;
}
.profile .char-name {
font-size: 50px;
font-family: NZBZ;
text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, 0.7);
text-align: right;
}
.profile .char-lv {
font-family: Number;
margin-bottom: 20px;
text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, 0.7);
text-align: right;
}
.profile .attr {
border-radius: 4px;
overflow: hidden;
}
.profile .detail li {
width: 300px;
font-size: 17px;
list-style: none;
padding: 0 100px 0 35px;
position: relative;
font-family: YS;
height: 32px;
line-height: 32px;
text-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
}
.profile .attr li i {
display: inline-block;
height: 20px;
width: 20px;
background-image: url("../../character/icon.png");
background-size: auto 20px;
position: absolute;
left: 10px;
top: 8px;
opacity: 0.9;
transform: scale(0.9);
}
.profile .i-hp {
background-position: -20px 0;
}
.profile .i-atk {
background-position: -40px 0;
}
.profile .i-def {
background-position: -60px 0;
}
.profile .i-mastery {
background-position: -80px 0;
}
.profile .i-cr {
background-position: -100px 0;
}
.profile .i-cd {
background-position: -140px 0;
}
.profile .i-re {
background-position: -120px 0;
}
.profile .i-dmg {
background-position: -160px 0;
}
.profile .detail li:nth-child(even) {
background: rgba(0, 0, 0, 0.4);
}
.profile .detail li:nth-child(odd) {
background: rgba(50, 50, 50, 0.4);
}
.profile .detail li strong {
display: inline-block;
position: absolute;
right: 85px;
text-align: right;
font-family: Number, sans-serif;
font-weight: normal;
}
.profile .detail li span {
position: absolute;
right: 0;
text-align: left;
width: 75px;
display: inline-block;
font-family: Number, sans-serif;
color: #90e800;
font-size: 15px;
}
.profile .talent-icon {
width: 100px;
height: 100px;
padding: 5px;
display: table;
border-radius: 50%;
position: relative;
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
z-index: 90;
}
.profile .talent-icon img,
.profile .talent-icon .profile .talent-icon-img {
width: 46%;
height: 46%;
position: absolute;
top: 50%;
left: 50%;
margin: -22% 0 0 -23%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.profile .talent-icon span {
background: #fff;
width: 34px;
height: 26px;
line-height: 26px;
font-size: 17px;
text-align: center;
border-radius: 5px;
position: absolute;
bottom: 2px;
left: 50%;
margin-left: -15px;
color: #000;
box-shadow: 0 0 5px 0 #000;
font-family: Number;
}
.profile .talent-icon.talent-plus span {
background: #2e353e;
color: #ffdfa0;
font-weight: bold;
box-shadow: 0 0 1px 0 #d3bc8e, 1px 1px 2px 0 rgba(0, 0, 0, 0.5);
}
.profile .talent-icon.talent-crown:after {
content: "";
display: block;
width: 28px;
height: 28px;
background: url("../character/imgs/crown.png") no-repeat;
background-size: contain;
position: absolute;
left: 50%;
top: 0;
margin-left: -14px;
}
.profile .char-talents {
display: flex;
width: 300px;
margin-bottom: 10px;
}
.profile .char-cons .talent-item,
.profile .char-talents .talent-item {
flex: 1;
}
.profile .char-cons {
display: flex;
width: 250px;
position: absolute;
bottom: 5px;
left: 20px;
}
.profile .char-cons .talent-icon {
width: 50px;
height: 50px;
margin: 0 -5px;
}
.profile .char-cons .talent-icon.off {
filter: grayscale(100%);
opacity: 0.4;
}
/*# sourceMappingURL=avatar-profile-source.css.map */

View File

@@ -0,0 +1,113 @@
.item-card {
width: 52px;
margin: 0px 0 5px 7px;
position: relative;
}
.item-card .badge {
overflow: hidden;
border-radius: 5px;
position: relative;
background: #e9e5dc;
box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3);
}
.item-card .badge img {
width: 100%;
overflow: hidden;
background-size: 100%;
background-repeat: no-repeat;
position: absolute;
top: 0;
/*filter: contrast(95%);*/
}
.item-card .bg1 {
background-image: url("imgs/bg1.png");
width: 100%;
height: 70px;
background-size: 100%;
background-repeat: no-repeat;
}
.item-card .bg2 {
background-image: url("imgs/bg2.png");
width: 100%;
height: 70px;
background-size: 100%;
background-repeat: no-repeat;
}
.item-card .bg3 {
background-image: url("imgs/bg3.png");
width: 100%;
height: 70px;
background-size: 100%;
background-repeat: no-repeat;
}
.item-card .bg4 {
background-image: url("imgs/bg4.png");
width: 100%;
height: 70px;
background-size: 100%;
background-repeat: no-repeat;
}
.item-card .bg5 {
background-image: url("imgs/bg5.png");
width: 100%;
height: 70px;
background-size: 100%;
background-repeat: no-repeat;
}
.item-card .box:after {
content: "";
display: block;
position: absolute;
width: 15px;
right: 0;
bottom: 15px;
}
.item-card .box .desc {
font-weight: 500;
text-align: center;
position: absolute;
bottom: 0;
background: #e9e5dc;
width: 100%;
height: 16px;
font-size: 12px;
line-height: 16px;
font-family: Number;
}
.item-card .box .name {
overflow: hidden;
white-space: nowrap;
margin-top: 5px;
font-weight: 500;
text-align: center;
font-size: 14px;
}
.item-card .life {
position: absolute;
top: 0px;
left: 0px;
z-index: 9;
font-size: 13px;
text-align: center;
color: #fff;
border-radius: 2px;
padding: 1px 4px;
border-radius: 3px;
font-family: "tttgbnumber";
}
.item-card .life1 {
background-color: #62a8ea;
}
.item-card .life2 {
background-color: #62a8ea;
}
.item-card .life3 {
background-color: #62a8ea;
}
.item-card .life4 {
background-color: #ff5722;
}
.item-card .life5 {
background-color: #ff5722;
}
/*# sourceMappingURL=item-card.less.map */

View File

@@ -0,0 +1,120 @@
.item-card {
width: 66px;
margin: 4px;
position: relative;
border-radius: 5px;
.badge {
overflow: hidden;
border-radius: 50%;
display: block;
width: 26px;
height: 26px;
position: absolute;
right: -4px;
top: -4px;
background: #e9e5dc;
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.8), 2px 2px 2px rgba(50, 50, 50, .5);
z-index: 10;
img {
width: 140%;
left: -27%;
top: -45%;
overflow: hidden;
background-size: 100%;
background-repeat: no-repeat;
position: absolute;
}
}
.item-bg {
width: 100%;
padding: 100% 0 0;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
margin: 0;
}
each(range(5), {
.bg@{value} {
background-image: url("./item/bg@{value}.png");
border-radius: 5px 5px 15px 0;
}
.bg-@{value} {
background-image: url("./item/bg@{value}.png");
border-radius: 5px 5px 15px 0;
}
})
.box {
border-radius: 5px;
overflow: hidden;
background: #e9e5dc;
.item-desc {
display: block;
font-weight: 500;
text-align: center;
bottom: 0;
background: #e9e5dc;
width: 100%;
font-size: 12px;
line-height: 16px;
white-space: nowrap;
overflow: hidden;
padding: 0 3px;
&:last-child {
padding-bottom: 2px;
}
}
.name {
overflow: hidden;
white-space: nowrap;
margin-top: 5px;
font-weight: 500;
text-align: center;
font-size: 14px;
}
.item-img {
width: 100%;
overflow: hidden;
background-size: 100%;
background-repeat: no-repeat;
position: absolute;
top: 0;
}
}
.item-life {
position: absolute;
top: 0;
left: 0;
z-index: 9;
font-size: 13px;
text-align: center;
color: #fff;
padding: 1px 4px;
border-radius: 3px;
}
.life(@idx, @color) {
.life@{idx} {
background-color: @color;
}
}
.life(1, #62a8ea);
.life(2, #62a8ea);
.life(3, #62a8ea);
.life(4, #ff5722);
.life(5, #ff5722);
}

View File

@@ -0,0 +1,61 @@
{{set ds = $data[0] || false }}
{{set {_res_path, icon,lvs,type} = $data[1]}}
<div class="talent-line">
<div class="talent-icon">
<img src="{{_res_path}}{{icon}}"/>
</div>
<div class="talent-info">
<div class="talent-name">{{ds.name}}</div>
<div class="talent-desc">
{{each ds.desc d}}
{{ if d[0] === "<" }}
{{@d}}
{{else if d!=""}}
<p>{{d}}</p>
{{/if}}
{{/each}}
</div>
</div>
{{if ds.tables && ds.tables.length > 0}}
<div class="talent-common-info">
{{each ds.tables tr}}
{{if tr.isSame}}
<div>
<strong>{{tr.name}}{{if tr.unit}}({{tr.unit}}){{/if}}</strong>
<span>{{tr.values[0]}}</span>
</div>
{{/if}}
{{/each}}
</div>
<table class="talent-table cont-table">
<tr class="tr">
<td class="th"></td>
{{each lvs lv idx}}
{{if (type=="a" && idx>4 && idx<11) || (type!="a" && idx>4 && idx < 13)}}
<td class="th lv">{{lv}}</td>
{{/if}}
{{/each}}
</tr>
{{each ds.tables tr}}
{{if !tr.isSame}}
<tr class="tr">
<td class="th talent-name">
{{tr.name}}
{{if tr.unit}}
<span class="unit">({{tr.unit}})</span>
{{/if}}
</td>
{{each tr.values v idx}}
{{if (type=="a" && idx>4 && idx<11) || (type!="a" && idx>4 && idx < 13)}}
<td class="td">{{v}}</td>
{{/if}}
{{/each}}
{{/if}}
</tr>
{{/each}}
</table>
{{/if}}
</div>

BIN
resources/help/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

83
resources/help/index.css Normal file
View File

@@ -0,0 +1,83 @@
body {
transform: scale(1);
width: 830px;
background: url("../common/theme/bg-01.jpg");
}
.container {
background: url(../common/theme/main-01.png) top left no-repeat;
background-size: 100% auto;
width: 830px;
}
.head-box {
margin: 60px 0 0 0;
padding-bottom: 0;
}
.head-box .title {
font-size: 50px;
}
.cont-box {
border-radius: 15px;
margin-top: 20px;
margin-bottom: 20px;
overflow: hidden;
box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.15);
position: relative;
}
.help-group {
font-size: 18px;
font-weight: bold;
padding: 15px 15px 10px 20px;
}
.help-table {
text-align: center;
border-collapse: collapse;
margin: 0;
border-radius: 0 0 10px 10px;
display: table;
overflow: hidden;
width: 100%;
color: #fff;
}
.help-table .tr {
display: table-row;
}
.help-table .td,
.help-table .th {
font-size: 14px;
display: table-cell;
box-shadow: 0 0 1px 0 #888 inset;
padding: 12px 0 12px 50px;
line-height: 24px;
position: relative;
text-align: left;
}
.help-table .tr:last-child .td {
padding-bottom: 12px;
}
.help-table .th {
background: rgba(34, 41, 51, 0.5);
}
.help-icon {
width: 40px;
height: 40px;
display: block;
position: absolute;
background: url("icon.png") 0 0 no-repeat;
background-size: 500px auto;
border-radius: 5px;
left: 6px;
top: 12px;
transform: scale(0.85);
}
.help-title {
display: block;
color: #d3bc8e;
font-size: 16px;
line-height: 24px;
}
.help-desc {
display: block;
font-size: 13px;
line-height: 18px;
}
/*# sourceMappingURL=index.css.map */

44
resources/help/index.html Normal file
View File

@@ -0,0 +1,44 @@
{{extend defaultLayout}}
{{block 'css'}}
<link rel="stylesheet" type="text/css" href="{{_res_path}}/help/index.css"/>
<% style = style.replace(/{{_res_path}}/g, _res_path) %>
{{@style}}
{{/block}}
{{block 'main'}}
<div class="info-box">
<div class="head-box type{{bgType}}">
<div class="title">{{helpCfg.title||"使用帮助"}}</div>
<div class="label">{{helpCfg.subTitle || "Yunzai-Bot & Miao-Plugin"}}</div>
</div>
</div>
{{each helpGroup group}}
{{set len = group?.list?.length || 0 }}
<div class="cont-box">
<div class="help-group">{{group.group}}</div>
{{if len > 0}}
<div class="help-table">
<div class="tr">
{{each group.list help idx}}
<div class="td">
<span class="help-icon" style="{{help.css}}"></span>
<strong class="help-title">{{help.title}}</strong>
<span class="help-desc">{{help.desc}}</span>
</div>
{{if idx%colCount === colCount-1 && idx>0 && idx< len-1}}
</div>
<div class="tr">
{{/if}}
{{/each}}
<% for(let i=(len-1)%colCount; i< colCount-1 ; i++){ %>
<div class="td"></div>
<% } %>
</div>
</div>
{{/if}}
</div>
{{/each}}
{{/block}}

96
resources/help/index.less Normal file
View File

@@ -0,0 +1,96 @@
body {
transform: scale(1);
width: 830px;
background: url("../common/theme/bg-01.jpg");
}
.container {
background: url(../common/theme/main-01.png) top left no-repeat;
background-size: 100% auto;
width: 830px;
}
.head-box {
margin: 60px 0 0 0;
padding-bottom: 0;
}
.head-box .title {
font-size: 50px;
}
.cont-box {
border-radius: 15px;
margin-top: 20px;
margin-bottom: 20px;
overflow: hidden;
box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%);
position: relative;
}
.help-group {
font-size: 18px;
font-weight: bold;
padding: 15px 15px 10px 20px;
}
.help-table {
text-align: center;
border-collapse: collapse;
margin: 0;
border-radius: 0 0 10px 10px;
display: table;
overflow: hidden;
width: 100%;
color: #fff;
}
.help-table .tr {
display: table-row;
}
.help-table .td,
.help-table .th {
font-size: 14px;
display: table-cell;
box-shadow: 0 0 1px 0 #888 inset;
padding: 12px 0 12px 50px;
line-height: 24px;
position: relative;
text-align: left;
}
.help-table .tr:last-child .td {
padding-bottom: 12px;
}
.help-table .th {
background: rgba(34, 41, 51, .5)
}
.help-icon {
width: 40px;
height: 40px;
display: block;
position: absolute;
background: url("icon.png") 0 0 no-repeat;
background-size: 500px auto;
border-radius: 5px;
left: 6px;
top: 12px;
transform: scale(0.85);
}
.help-title {
display: block;
color: #d3bc8e;
font-size: 16px;
line-height: 24px;
}
.help-desc {
display: block;
font-size: 13px;
line-height: 18px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,24 @@
export const style = {
// 主文字颜色
fontColor: '#ceb78b',
// 主文字阴影: 横向距离 垂直距离 阴影大小 阴影颜色
// fontShadow: '0px 0px 1px rgba(6, 21, 31, .9)',
fontShadow: 'none',
// 描述文字颜色
descColor: '#eee',
/* 面板整体底色,会叠加在标题栏及帮助行之下,方便整体帮助有一个基础底色
* 若无需此项可将rgba最后一位置为0即为完全透明
* 注意若综合透明度较低,或颜色与主文字颜色过近或太透明可能导致阅读困难 */
contBgColor: 'rgba(6, 21, 31, .5)',
// 面板底图毛玻璃效果数字越大越模糊0-10 ,可为小数
contBgBlur: 3,
// 板块标题栏底色
headerBgColor: 'rgba(6, 21, 31, .4)',
// 帮助奇数行底色
rowBgColor1: 'rgba(6, 21, 31, .2)',
// 帮助偶数行底色
rowBgColor2: 'rgba(6, 21, 31, .35)'
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 KiB

View File

@@ -0,0 +1,24 @@
【default皮肤】
default为默认皮肤不建议改动防止后续更新冲突
如不想使用default可创建或下载其他皮肤存在其他皮肤时会默认忽略default皮肤
【增加自定义皮肤】
可创建或下载皮肤包,放置在当前目录(theme)下,皮肤名称为皮肤文件夹名字
皮肤包内应包含的文件:
main.png主图高度自适应
bg.jpg背景图如果main.png图片不够高或存在透明的话则会使用bg.jpg作为背景进行填充
config.js当前皮肤元素的颜色、透明度等配置可选。如无此文件会使用默认配置如需自定义可参考default/config.js
【皮肤选择】
默认为随机皮肤如需指定固定某个皮肤可到config/help.js中设置theme的字段选项
在有其他皮肤时会默认忽略自带的default皮肤
如希望default皮肤也出现在随机中可修改config/help.js将themeExclude中配置的default项删掉
如需临时增加其他皮肤屏蔽也可以追加至themeExclude中当然也可以直接删掉对应皮肤
新增皮肤或修改配置后无需重启,可直接生效

View File

@@ -0,0 +1,68 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
font-size: 18px;
color: #1e1f20;
transform: scale(1.3);
transform-origin: 0 0;
width: 520px;
}
.container {
width: 520px;
padding: 10px 0 10px 0;
background-size: 100% 100%;
}
.log-cont {
background-size: cover;
margin: 5px 15px 5px 10px;
border-radius: 10px;
}
.log-cont .cont {
margin: 0;
}
.log-cont .cont-title {
font-size: 16px;
padding: 10px 20px 6px;
}
.log-cont .cont-title.current-version {
font-size: 20px;
}
.log-cont ul {
font-size: 14px;
padding-left: 20px;
}
.log-cont ul li {
margin: 3px 0;
}
.log-cont ul.sub-log-ul li {
margin: 1px 0;
}
.log-cont .cmd {
color: #d3bc8e;
display: inline-block;
border-radius: 3px;
background: rgba(0, 0, 0, 0.5);
padding: 0 3px;
margin: 1px 2px;
}
.log-cont .strong {
color: #24d5cd;
}
.log-cont .new {
display: inline-block;
width: 18px;
margin: 0 -3px 0 1px;
}
.log-cont .new:before {
content: "NEW";
display: inline-block;
transform: scale(0.6);
transform-origin: 0 0;
color: #d3bc8e;
white-space: nowrap;
}
/*# sourceMappingURL=version-info.css.map */

View File

@@ -0,0 +1,35 @@
{{extend elemLayout}}
{{block 'css'}}
<link rel="stylesheet" type="text/css" href="{{_res_path}}/help/version-info.css"/>
{{/block}}
{{block 'main'}}
{{each changelogs ds idx}}
<div class="hydro-bg log-cont">
<div class="cont">
{{if idx === 0 }}
<div class="cont-title current-version">当前版本 {{ds.version}}</div>
{{else}}
<div class="cont-title">小飞版本 {{ds.version}}</div>
{{/if}}
<div class="cont-body">
<ul class="log-ul">
{{each ds.logs log}}
<li>
<p>{{@log.title}}</p>
{{if log.logs.length > 0}}
<ul class="sub-log-ul">
{{each log.logs ls}}
<li>{{@ls}}</li>
{{/each}}
</ul>
{{/if}}
</li>
{{/each}}
</ul>
</div>
</div>
</div>
{{/each}}
{{/block}}

View File

@@ -0,0 +1,90 @@
.linear-bg(@color) {
background-image: linear-gradient(to right, @color, @color 80%, fade(@color, 0) 100%);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
font-size: 18px;
color: #1e1f20;
transform: scale(1.3);
transform-origin: 0 0;
width: 520px;
}
.container {
width: 520px;
padding: 10px 0 10px 0;
background-size: 100% 100%;
}
.log-cont {
background-size: cover;
margin: 5px 15px 5px 10px;
border-radius: 10px;
.cont {
margin: 0;
}
.cont-title {
font-size: 16px;
padding: 10px 20px 6px;
&.current-version {
font-size: 20px;
}
}
.cont-body {
}
ul {
font-size: 14px;
padding-left: 20px;
li {
margin: 3px 0;
}
&.sub-log-ul {
li {
margin: 1px 0;
}
}
}
.cmd {
color: #d3bc8e;
display: inline-block;
border-radius: 3px;
background: rgba(0, 0, 0, 0.5);
padding: 0 3px;
margin: 1px 2px;
}
.strong {
color: #24d5cd;
}
.new {
display: inline-block;
width: 18px;
margin: 0 -3px 0 1px;
}
.new:before {
content: "NEW";
display: inline-block;
transform: scale(0.6);
transform-origin: 0 0;
color: #d3bc8e;
white-space: nowrap;
}
}