Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
2128d0cd80 | |||
9f6b3acf9a | |||
7367c9047f | |||
a109a58c87 | |||
9100d2d431 | |||
c6d0c24b90 | |||
d0cab93fca | |||
2da259e7e7 | |||
ff8d66572c | |||
3c4b55b0b9 | |||
d65addd516 | |||
3314fab761 | |||
5fd12b9365 | |||
88d8ee593c |
28
README.md
@ -1,16 +1,17 @@
|
|||||||
# BLive Coyote
|
# BLive Coyote
|
||||||
|
> [!CAUTION]
|
||||||
|
> 本项目仅供学习使用,请勿用于直播过程中!
|
||||||
|
|
||||||
郊狼B站直播玩法:送礼物控制郊狼主机输出
|
郊狼B站直播玩法:送礼物控制郊狼主机输出
|
||||||
|
|
||||||
## 项目简介
|
## 项目简介
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> 本项目仍在开发中,目前已可以基本使用,欢迎体验。
|
> 本项目仍在开发中,目前已可以基本使用。
|
||||||
>
|
>
|
||||||
> 本项目为个人学习项目,如有错误敬请批评指正,欢迎 PR。
|
> 本项目为个人学习项目,如有错误敬请批评指正,欢迎 PR。
|
||||||
|
|
||||||
本项目以 [Bilibili 直播&互玩 JavaScript Demo](https://open-live.bilibili.com/document/a7bd5377-ad7d-a273-25ae-28caf37a7a85) 和 [DG-LAB SOCKET控制-控制端开源](https://github.com/DG-LAB-OPENSOURCE/DG-LAB-OPENSOURCE/tree/main/socket) 为基础,实现了直播间送礼物控制郊狼主机输出的功能。
|
本项目以 [Bilibili 直播&互玩 JavaScript Demo](https://open-live.bilibili.com/document/a7bd5377-ad7d-a273-25ae-28caf37a7a85) 和 [DG-LAB SOCKET控制-控制端开源](https://github.com/DG-LAB-OPENSOURCE/DG-LAB-OPENSOURCE/tree/main/socket) 为基础,实现了直播间送礼物控制郊狼主机输出的功能。
|
||||||
|
|
||||||
演示视频:[郊狼直播互动玩法正式发布【BLive Coyote】](https://www.bilibili.com/video/BV1D1421i7WB/)
|
|
||||||
|
|
||||||
- 郊狼 WebSocket 后端请参考:[DG-LAB-OPENSOURCE](https://github.com/DG-LAB-OPENSOURCE/DG-LAB-OPENSOURCE/tree/main/socket/BackEnd(Node))
|
- 郊狼 WebSocket 后端请参考:[DG-LAB-OPENSOURCE](https://github.com/DG-LAB-OPENSOURCE/DG-LAB-OPENSOURCE/tree/main/socket/BackEnd(Node))
|
||||||
- 哔哩哔哩直播互动玩法服务端请参考:[JavaScript Demo](https://open-live.bilibili.com/document/a7bd5377-ad7d-a273-25ae-28caf37a7a85)
|
- 哔哩哔哩直播互动玩法服务端请参考:[JavaScript Demo](https://open-live.bilibili.com/document/a7bd5377-ad7d-a273-25ae-28caf37a7a85)
|
||||||
|
|
||||||
@ -27,6 +28,7 @@
|
|||||||
```
|
```
|
||||||
BLive_Coyote
|
BLive_Coyote
|
||||||
├─public
|
├─public
|
||||||
|
│ ├─img
|
||||||
│ └─css
|
│ └─css
|
||||||
└─src
|
└─src
|
||||||
├─assets
|
├─assets
|
||||||
@ -36,8 +38,26 @@ BLive_Coyote
|
|||||||
|
|
||||||
## 项目启动
|
## 项目启动
|
||||||
```bash
|
```bash
|
||||||
cd Client
|
cd BLive_Coyote
|
||||||
npm install
|
npm install
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
主播身份码及 app_id 获取请参考 [开放平台-直播&互玩接入文档:常见问题](https://open-live.bilibili.com/document/5dffc297-6fd2-41ff-bd45-6e8b89e2a68e)
|
主播身份码及 app_id 获取请参考 [开放平台-直播&互玩接入文档:常见问题](https://open-live.bilibili.com/document/5dffc297-6fd2-41ff-bd45-6e8b89e2a68e)
|
||||||
|
|
||||||
|
## 安全须知
|
||||||
|
> [!CAUTION]
|
||||||
|
> 使用本项目或郊狼前务必认真阅读安全须知
|
||||||
|
|
||||||
|
- **请保证在安全、清醒、自愿的情况下使用**
|
||||||
|
- 严禁**体内存在电子/金属植入物者、心脑血管疾病患者、孕妇、儿童或无法及时操作主机**的人群使用
|
||||||
|
- 严禁将电极置于**心脏投影区**(或任何可能使电流经过心脏的位置),以及**头部、颈部、皮肤破损处**等位置
|
||||||
|
- 严禁在驾驶或操纵机器等危险情况下使用
|
||||||
|
- 请勿在同一部位连续使用**30分钟以上**,以免造成损伤
|
||||||
|
- 请勿在**输出状态下**移动电极,以免造成刺痛或灼伤
|
||||||
|
- 在直播过程中使用**可能会导致直播间被封禁**,风险自负
|
||||||
|
- 在使用前需要**完整阅读郊狼产品安全须知,并设置好强度上限保护**。
|
||||||
|
|
||||||
|
## 特别感谢
|
||||||
|
感谢 VUP [鱼芷white](https://space.bilibili.com/3546608125872618/)、[叶秋zi](https://space.bilibili.com/415235891/) 帮助测试
|
||||||
|
|
||||||
|
排名不分先后
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="zh-cn">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
@ -684,3 +684,68 @@ select {
|
|||||||
background-color: #ffe99d;
|
background-color: #ffe99d;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-window {
|
||||||
|
position: fixed;
|
||||||
|
top: 10%;
|
||||||
|
bottom: 10%;
|
||||||
|
height: 500px;
|
||||||
|
left: 10%;
|
||||||
|
right: 10%;
|
||||||
|
background-color: #171717;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: #ffe99d 2px solid;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.settings-window-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
.settings-window-body::-webkit-scrollbar {
|
||||||
|
width: 10px; /* 宽度 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-window-body::-webkit-scrollbar-track {
|
||||||
|
background: transparent; /* 轨道颜色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-window-body::-webkit-scrollbar-thumb {
|
||||||
|
background: #ffe99d; /* 滚动条颜色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-window-body::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #ffe99d; /* 滚动条鼠标悬停颜色 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
background: #fce9a7;
|
||||||
|
color: #000;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-window-bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animated-notice {
|
||||||
|
opacity: 0;
|
||||||
|
animation: fadeIn 1s ease-in-out forwards;
|
||||||
|
animation-delay: 1.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b {
|
||||||
|
color: #fce9a7;
|
||||||
|
}
|
||||||
|
BIN
public/img/31087.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
public/img/31088.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
public/img/31538.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
public/img/31589.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
public/img/31591.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
public/img/31891.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
public/img/31932.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
public/img/31933.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
public/img/32089.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
public/img/32126.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/img/32199.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
public/img/32292.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/img/32293.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
public/img/32360.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/img/32363.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
public/img/32612.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
public/img/32735.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
public/img/34115.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/img/39.png
Normal file
After Width: | Height: | Size: 523 KiB |
353
src/App.vue
@ -1,15 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// This starter template is using Vue 3 <script setup> SFCs
|
// This starter template is using Vue 3 <script setup> SFCs
|
||||||
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
|
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
|
||||||
import { ref, watch } from "vue"
|
import {computed, ref, watch} from "vue"
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { Notyf } from 'notyf'
|
import { Notyf } from 'notyf'
|
||||||
import { createSocket, destroySocket } from "./socket/index"
|
import {createSocket, destroySocket, waveCounter} from "./socket/index"
|
||||||
import {
|
import {
|
||||||
createCoyoteSocket,
|
createCoyoteSocket,
|
||||||
closeCoyoteSocket,
|
closeCoyoteSocket,
|
||||||
addOrIncrease,
|
addOrIncrease,
|
||||||
sendWaveData,
|
sendWaveData,
|
||||||
|
coyoteState,
|
||||||
qrcodeSrc,
|
qrcodeSrc,
|
||||||
qrcodeShow,
|
qrcodeShow,
|
||||||
channelAStrength,
|
channelAStrength,
|
||||||
@ -30,19 +31,62 @@ const api = axios.create({
|
|||||||
|
|
||||||
//读取本地储存数据
|
//读取本地储存数据
|
||||||
let settings = ref()
|
let settings = ref()
|
||||||
|
let test_settings = ref()
|
||||||
|
const settings_text = localStorage.getItem('settings') || ''
|
||||||
|
const settings_version = 1
|
||||||
|
let showUpgrade = ref(false)
|
||||||
if (window.localStorage.getItem("settings")) {
|
if (window.localStorage.getItem("settings")) {
|
||||||
settings.value = JSON.parse(window.localStorage.getItem("settings") || '{}');
|
settings.value = JSON.parse(window.localStorage.getItem("settings") || '{}')
|
||||||
|
if (settings.value.version != settings_version) {
|
||||||
|
// 如果版本不一致,则提示是否修复
|
||||||
|
showUpgrade.value = true
|
||||||
|
}
|
||||||
// console.log(settings.value)
|
// console.log(settings.value)
|
||||||
} else {
|
} else {
|
||||||
// 如果没有,使用默认值并且保存
|
// 如果没有,使用默认值并且保存
|
||||||
settings.value = {
|
settings.value = {
|
||||||
|
version: 1,
|
||||||
waveData: waveData,
|
waveData: waveData,
|
||||||
strengthData: strengthData,
|
strengthData: strengthData,
|
||||||
guardLevel: 0
|
guardLevel: 0,
|
||||||
};
|
fansMedal: false
|
||||||
window.localStorage.setItem('settings', JSON.stringify(settings.value));
|
}
|
||||||
|
window.localStorage.setItem('settings', JSON.stringify(settings.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window.localStorage.getItem("test")) {
|
||||||
|
test_settings.value = JSON.parse(window.localStorage.getItem("test") || '{}')
|
||||||
|
} else {
|
||||||
|
test_settings.value = {
|
||||||
|
falloff: [0, 0]
|
||||||
|
}
|
||||||
|
window.localStorage.setItem('test', JSON.stringify(test_settings.value))
|
||||||
|
}
|
||||||
|
let showSafetyNotice = ref(localStorage.getItem('showSafetyNotice') !== 'false')
|
||||||
|
|
||||||
|
const upgradeSettings = () => {
|
||||||
|
// 目前结构没变化,所以补全不存在的项就行了
|
||||||
|
const old_settings = JSON.parse(window.localStorage.getItem("settings") || '{}')
|
||||||
|
const old_waveData = old_settings?.waveData ? old_settings.waveData : waveData
|
||||||
|
const old_strengthData = old_settings?.strengthData ? old_settings.strengthData : strengthData
|
||||||
|
const old_guardLevel = old_settings?.guardLevel ? old_settings.guardLevel : "0"
|
||||||
|
const old_fansMedal = old_settings?.fansMedal ? old_settings.fansMedal : false
|
||||||
|
|
||||||
|
settings.value = {
|
||||||
|
version: settings_version,
|
||||||
|
waveData: old_waveData,
|
||||||
|
strengthData: old_strengthData,
|
||||||
|
guardLevel: old_guardLevel,
|
||||||
|
fansMedal: old_fansMedal
|
||||||
|
}
|
||||||
|
|
||||||
|
window.localStorage.setItem('settings', JSON.stringify(settings.value));
|
||||||
|
|
||||||
|
console.log(settings.value)
|
||||||
|
|
||||||
|
showUpgrade.value = false
|
||||||
|
notyf.success("升级成功")
|
||||||
|
}
|
||||||
|
|
||||||
// 替换你的主播身份码
|
// 替换你的主播身份码
|
||||||
const codeId = ref("")
|
const codeId = ref("")
|
||||||
@ -61,17 +105,69 @@ clearInterval(heartBeatTimer.value!)
|
|||||||
const waveTestData = ref("")
|
const waveTestData = ref("")
|
||||||
// 显示设置窗口
|
// 显示设置窗口
|
||||||
const showSettings = ref(false)
|
const showSettings = ref(false)
|
||||||
|
// 显示游戏开始警告
|
||||||
|
const showWarnWindow = ref(false)
|
||||||
|
const warnWindowCountdown = ref(5);
|
||||||
|
|
||||||
|
// 测试玩法
|
||||||
|
const showTestWindow = ref(false)
|
||||||
|
const maxHP = ref(1000)
|
||||||
|
const HP = ref(maxHP.value)
|
||||||
|
|
||||||
|
// 连接状态
|
||||||
|
const gameState = ref(false)
|
||||||
|
|
||||||
const selectedGift = ref('')
|
const selectedGift = ref('')
|
||||||
const selectedWave = ref('')
|
const selectedWave = ref('')
|
||||||
const relations = ref(Object.entries(giftData).map(([key, value]) => ({ gift: key, wave: settings.value.waveData[key] })))
|
const relations = ref(Object.entries(giftData).map(([key, value]) => ({ gift: key, wave: settings.value.waveData[key] })))
|
||||||
|
|
||||||
// console.log(relations.value)
|
// 安全须知相关
|
||||||
|
let canAcknowledgeSafetyNotice = ref(false)
|
||||||
|
let canAcknowledgeSafetyNoticeCountdown = ref(15)
|
||||||
|
let canAcknowledgeSafetyNoticeTimer = setInterval(() => {
|
||||||
|
canAcknowledgeSafetyNoticeCountdown.value--
|
||||||
|
if (canAcknowledgeSafetyNoticeCountdown.value <= 0) {
|
||||||
|
canAcknowledgeSafetyNotice.value = true
|
||||||
|
clearInterval(canAcknowledgeSafetyNoticeTimer)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
let safetyNotices = ref([
|
||||||
|
"<b>请保证在安全、清醒、自愿的情况下使用</b>",
|
||||||
|
"严禁<b>体内存在电子/金属植入物者、心脑血管疾病患者、孕妇、儿童或无法及时操作主机</b>的人群使用",
|
||||||
|
"严禁将电极置于<b>心脏投影区</b>(或任何可能使电流经过心脏的位置),以及<b>头部、颈部、皮肤破损处</b>等位置",
|
||||||
|
"严禁在驾驶或操纵机器等危险情况下使用",
|
||||||
|
"请勿在同一部位连续使用<b>30分钟以上</b>,以免造成损伤",
|
||||||
|
"请勿在<b>输出状态下</b>移动电极,以免造成刺痛或灼伤",
|
||||||
|
"在直播过程中使用<b>可能会导致直播间被封禁</b>,风险自负",
|
||||||
|
"在使用前需要<b>完整阅读郊狼产品安全须知,并设置好强度上限保护</b>",
|
||||||
|
])
|
||||||
|
|
||||||
watch(selectedGift, (newGift) => {
|
watch(selectedGift, (newGift) => {
|
||||||
selectedWave.value = waveData[newGift]
|
selectedWave.value = waveData[newGift]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(showWarnWindow, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
let timer = setInterval(() => {
|
||||||
|
warnWindowCountdown.value--;
|
||||||
|
if (warnWindowCountdown.value <= 0) {
|
||||||
|
clearInterval(timer);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
warnWindowCountdown.value = 5; // 重置倒计时
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(waveCounter, () => {
|
||||||
|
HP.value = Math.max(0, HP.value - channelAStrength.value)
|
||||||
|
});
|
||||||
|
|
||||||
|
const fansMedal = computed({
|
||||||
|
get: () => settings.value.fansMedal,
|
||||||
|
set: (value) => { settings.value.fansMedal = value === 'true' }
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试请求鉴权接口
|
* 测试请求鉴权接口
|
||||||
@ -79,8 +175,14 @@ watch(selectedGift, (newGift) => {
|
|||||||
const getAuth = () => {
|
const getAuth = () => {
|
||||||
api.post("/getAuth", {})
|
api.post("/getAuth", {})
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
|
if (typeof data.code !== "number") {
|
||||||
|
console.log("-----鉴权失败-----")
|
||||||
|
notyf.error({ message: "服务端异常" })
|
||||||
|
return
|
||||||
|
} else {
|
||||||
console.log("-----鉴权成功-----")
|
console.log("-----鉴权成功-----")
|
||||||
notyf.success({ message: "鉴权成功" })
|
notyf.success({ message: "鉴权成功" })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("-----鉴权失败-----")
|
console.log("-----鉴权失败-----")
|
||||||
@ -127,6 +229,8 @@ const gameStart = () => {
|
|||||||
heartBeatThis(game_info.game_id)
|
heartBeatThis(game_info.game_id)
|
||||||
}, 20000)
|
}, 20000)
|
||||||
handleCreateSocket()
|
handleCreateSocket()
|
||||||
|
showLiveWarn()
|
||||||
|
gameState.value = true
|
||||||
} else {
|
} else {
|
||||||
console.log("-----游戏开始失败-----")
|
console.log("-----游戏开始失败-----")
|
||||||
console.log("原因:", data)
|
console.log("原因:", data)
|
||||||
@ -160,6 +264,7 @@ const gameEnd = () => {
|
|||||||
handleDestroySocket()
|
handleDestroySocket()
|
||||||
console.log("-----心跳关闭成功-----")
|
console.log("-----心跳关闭成功-----")
|
||||||
notyf.success({ message: "游戏关闭成功" })
|
notyf.success({ message: "游戏关闭成功" })
|
||||||
|
gameState.value = false
|
||||||
} else {
|
} else {
|
||||||
console.log("-----游戏关闭失败-----")
|
console.log("-----游戏关闭失败-----")
|
||||||
console.log("原因:", data)
|
console.log("原因:", data)
|
||||||
@ -228,6 +333,10 @@ const saveSettings = () => {
|
|||||||
window.localStorage.setItem('settings', JSON.stringify(settings.value));
|
window.localStorage.setItem('settings', JSON.stringify(settings.value));
|
||||||
console.log(settings.value);
|
console.log(settings.value);
|
||||||
}
|
}
|
||||||
|
const saveTestSettings = () => {
|
||||||
|
window.localStorage.setItem('test', JSON.stringify(test_settings.value));
|
||||||
|
console.log(test_settings.value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加并保存 waveData
|
* 添加并保存 waveData
|
||||||
@ -251,6 +360,43 @@ const addRelationAndSave = () => {
|
|||||||
// 保存设置
|
// 保存设置
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阅读安全须知
|
||||||
|
*/
|
||||||
|
const acknowledgeSafetyNotice = () => {
|
||||||
|
showSafetyNotice.value = false
|
||||||
|
localStorage.setItem('showSafetyNotice', 'false')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示直播警告
|
||||||
|
*/
|
||||||
|
const showLiveWarn = () => {
|
||||||
|
showWarnWindow.value = true
|
||||||
|
// 五秒后关闭
|
||||||
|
setTimeout(() => {
|
||||||
|
showWarnWindow.value = false
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数字大航海等级转换为文字
|
||||||
|
*/
|
||||||
|
const guardLevelText = computed(() => {
|
||||||
|
switch (settings.value.guardLevel) {
|
||||||
|
case "0":
|
||||||
|
return "观众";
|
||||||
|
case "1":
|
||||||
|
return "舰长";
|
||||||
|
case "2":
|
||||||
|
return "提督";
|
||||||
|
case "3":
|
||||||
|
return "总督";
|
||||||
|
default:
|
||||||
|
return "未知";
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -267,15 +413,120 @@ const addRelationAndSave = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-window-bg" v-show="showUpgrade || showSettings || showSafetyNotice || showWarnWindow"></div>
|
||||||
|
|
||||||
|
<div class="settings-window" v-show="showUpgrade">
|
||||||
|
<h2>⚠ 本地设置数据升级</h2>
|
||||||
|
<p>
|
||||||
|
目前可读取的本地设置数据的储存结构版本为<input class="tag" v-model="settings_version" size="1" disabled>,你的设备上现有的设置数据的储存结构版本为<input class="tag" v-model="settings.version" size="1" disabled>。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
为了可以安全使用 BLive Coyote,现在需要将你设备上储存的设置数据进行升级,这个过程通常可以自动进行,如果出现意外请联系开发者。
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<p>【注意】下面是你的全部设置数据,请先复制下面的全部内容,以确保在升级失败时可以恢复!</p>
|
||||||
|
<textarea v-model="settings_text" style="width: 100%; height: 64px;"></textarea>
|
||||||
|
<div class="form">
|
||||||
|
<button @click="upgradeSettings">尝试执行升级</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-window" v-show="showSafetyNotice">
|
||||||
|
<h2>⚠ 安全须知</h2>
|
||||||
|
<p v-for="(notice, index) in safetyNotices"
|
||||||
|
:key="index" class="animated-notice"
|
||||||
|
:style="`animation-delay: ${index*2}s`"
|
||||||
|
v-html="notice">
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<p>【注意】请仔细阅读以上内容后,点击“<b>我已知晓</b>”</p>
|
||||||
|
<div class="form">
|
||||||
|
<button @click="acknowledgeSafetyNotice" :disabled="!canAcknowledgeSafetyNotice">
|
||||||
|
我已知晓{{canAcknowledgeSafetyNoticeCountdown != 0 ? "(" + canAcknowledgeSafetyNoticeCountdown + ")" : ""}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="warn-window" v-show="showWarnWindow">
|
||||||
|
<div style="font-size: 52px">
|
||||||
|
<b>⚠</b>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div style="margin: auto">
|
||||||
|
<b>【注意】</b>请不要在直播过程中展示或使用郊狼主机及配件,直播务必遵守平台规则,否则可能导致账号被封禁!继续即自愿承担可能存在的风险。({{ warnWindowCountdown }})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-window" style="background-color: #0a9a38; font-weight: bold;" v-show="showTestWindow">
|
||||||
|
<div class="settings-window-btn">
|
||||||
|
<button @click="showTestWindow = false" style="float: right">关</button>
|
||||||
|
</div>
|
||||||
|
<div class="settings-window-body">
|
||||||
|
<h2>测试界面</h2>
|
||||||
|
<hr />
|
||||||
|
<p>绿色背景方便用色度键抠像,最大 HP 为 <input v-model="maxHP" size="2" /></p>
|
||||||
|
<p><button @click="HP = maxHP">重置伤害</button> <button @click="HP -= 10">造成伤害</button></p>
|
||||||
|
<hr />
|
||||||
|
<div class="attack-box" style="padding-top: 25px;">
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div>
|
||||||
|
武器A
|
||||||
|
</div>
|
||||||
|
<div class="attack-a-board">
|
||||||
|
<div class="attack-a-bg" :style="{ width: (channelAStrength / softAStrength) * 100 + '%'}">
|
||||||
|
{{ channelAStrength + "/" + softAStrength }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div>
|
||||||
|
武器B
|
||||||
|
</div>
|
||||||
|
<div class="attack-a-board">
|
||||||
|
<div class="attack-a-bg" :style="{ width: (channelBStrength / softBStrength) * 100 + '%'}">
|
||||||
|
{{ channelBStrength + "/" + softBStrength }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="attribute-box">
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div style="margin: auto 0">
|
||||||
|
HP
|
||||||
|
</div>
|
||||||
|
<div class="attribute-hp-board">
|
||||||
|
<div class="attribute-hp-bg" :style="{ width: (HP / maxHP) * 100 + '%' }">
|
||||||
|
{{ HP + "/" + maxHP }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="settings-window" v-show="showSettings">
|
<div class="settings-window" v-show="showSettings">
|
||||||
|
<div class="settings-window-btn">
|
||||||
<button @click="showSettings = false" style="float: right">关</button>
|
<button @click="showSettings = false" style="float: right">关</button>
|
||||||
<button @click="saveSettings" style="float: right">存</button>
|
<button @click="saveSettings" style="float: right">存</button>
|
||||||
<div>
|
</div>
|
||||||
|
<div class="settings-window-body">
|
||||||
<h2>大航海</h2>
|
<h2>大航海</h2>
|
||||||
<p>
|
<p>
|
||||||
大航海等级达到
|
身份至低为
|
||||||
<input v-model="settings.guardLevel">
|
<select v-model="settings.guardLevel">
|
||||||
才可互动
|
<option value="0">观众</option>
|
||||||
|
<option value="1">舰长</option>
|
||||||
|
<option value="2">提督</option>
|
||||||
|
<option value="3">总督</option>
|
||||||
|
</select>
|
||||||
|
且
|
||||||
|
<select v-model="fansMedal">
|
||||||
|
<option value="true">需要</option>
|
||||||
|
<option value="false">不需要</option>
|
||||||
|
</select>
|
||||||
|
佩戴粉丝牌才可互动
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>强度规则</h2>
|
<h2>强度规则</h2>
|
||||||
@ -333,9 +584,20 @@ const addRelationAndSave = () => {
|
|||||||
</div>
|
</div>
|
||||||
<button @click="addRelationAndSave">新建或保存</button>
|
<button @click="addRelationAndSave">新建或保存</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2>实验功能</h2>
|
||||||
|
<div>
|
||||||
|
<p><b>⚠ 请勿依赖实验功能,实验功能可能在后续版本删除!</b></p>
|
||||||
|
<p>
|
||||||
|
每输出<input size="1" v-model="test_settings.falloff[0]" />次波形强度衰减<input size="1" v-model="test_settings.falloff[1]" />
|
||||||
|
(<span title="为了避免主包被电似,希望主包喜欢">?</span>)
|
||||||
|
</p>
|
||||||
|
<button @click="saveTestSettings">保存实验功能数据</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="game-tips">
|
<div class="game-tips">
|
||||||
! 请在连接前确保已经设置好强度上限
|
! 请在连接前确保已经设置好强度上限
|
||||||
</div>
|
</div>
|
||||||
@ -343,7 +605,7 @@ const addRelationAndSave = () => {
|
|||||||
<div class="game-info">
|
<div class="game-info">
|
||||||
<h2>主机状态</h2>
|
<h2>主机状态</h2>
|
||||||
|
|
||||||
<div style="display: flex">
|
<div class="dashboard" style="display: flex">
|
||||||
<div class="channel-circle">
|
<div class="channel-circle">
|
||||||
<div class="channel-tag">A</div>
|
<div class="channel-tag">A</div>
|
||||||
<div class="channel-strength">{{ channelAStrength }}</div>
|
<div class="channel-strength">{{ channelAStrength }}</div>
|
||||||
@ -360,7 +622,13 @@ const addRelationAndSave = () => {
|
|||||||
|
|
||||||
<h2>游戏玩法</h2>
|
<h2>游戏玩法</h2>
|
||||||
<h3>大航海</h3>
|
<h3>大航海</h3>
|
||||||
<p>等级达到 <input class="tag" v-model="settings.guardLevel" size="1" disabled> 才可互动</p>
|
<p>
|
||||||
|
身份至低为
|
||||||
|
<input class="tag" v-model="guardLevelText" size="1" disabled>
|
||||||
|
且
|
||||||
|
<span class="tag">{{ settings["fansMedal"] ? "需要" : "不需要" }}</span>
|
||||||
|
佩戴粉丝牌才可互动
|
||||||
|
</p>
|
||||||
<h3>强度控制</h3>
|
<h3>强度控制</h3>
|
||||||
<p>
|
<p>
|
||||||
赠送
|
赠送
|
||||||
@ -381,13 +649,11 @@ const addRelationAndSave = () => {
|
|||||||
<div v-for="relation in relations" :key="relation.gift">
|
<div v-for="relation in relations" :key="relation.gift">
|
||||||
<div v-if="relation && relation.wave">
|
<div v-if="relation && relation.wave">
|
||||||
<img :src="'/img/' + relation.gift + '.png'" width="24" :alt="giftData[relation.gift]">
|
<img :src="'/img/' + relation.gift + '.png'" width="24" :alt="giftData[relation.gift]">
|
||||||
<input class="tag" v-model="giftData[relation.gift]" disabled>
|
<input class="tag" v-model="giftData[relation.gift]" size="8" disabled>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button @click="showSettings = true">修改玩法</button>
|
<button @click="showSettings = true">修改玩法</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -397,16 +663,17 @@ const addRelationAndSave = () => {
|
|||||||
<input type="password" placeholder="填写主播身份码" v-model="codeId"/>
|
<input type="password" placeholder="填写主播身份码" v-model="codeId"/>
|
||||||
<label>app_id</label>
|
<label>app_id</label>
|
||||||
<input type="text" placeholder="填写 app_id" v-model="appId" />
|
<input type="text" placeholder="填写 app_id" v-model="appId" />
|
||||||
<button @click="gameStart">游戏开始</button>
|
<button @click="gameStart" v-show="!gameState">游戏开始</button>
|
||||||
<button @click="gameEnd">游戏结束</button>
|
<button @click="gameEnd" v-show="gameState">游戏结束</button>
|
||||||
<button @click="createCoyoteSocket">连接郊狼</button>
|
<button @click="createCoyoteSocket" v-show="!coyoteState">连接郊狼</button>
|
||||||
<button @click="closeCoyoteSocket">断开郊狼</button>
|
<button @click="closeCoyoteSocket" v-show="coyoteState">断开郊狼</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h2>调试选项</h2>
|
<h2>调试选项</h2>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
|
<button @click="showTestWindow = true">测试界面</button>
|
||||||
<button @click="getAuth">鉴权</button>
|
<button @click="getAuth">鉴权</button>
|
||||||
<label>波形数组 <a onclick="window.open('waveHelper.html', '', 'width=500,height=1000,left=700');">波形助手</a></label>
|
<label>波形数组 <a onclick="window.open('waveHelper.html', '', 'width=500,height=1000,left=700');">波形助手</a></label>
|
||||||
<input type="text" placeholder="填写欲测试的波形数组" v-model="waveTestData" />
|
<input type="text" placeholder="填写欲测试的波形数组" v-model="waveTestData" />
|
||||||
@ -432,23 +699,49 @@ const addRelationAndSave = () => {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-window {
|
.warn-window {
|
||||||
|
display: flex;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 10%;
|
top: 40%;
|
||||||
bottom: 10%;
|
bottom: 40%;
|
||||||
height: 500px;
|
left: 20%;
|
||||||
left: 10%;
|
right: 20%;
|
||||||
right: 10%;
|
background-color: #a00;
|
||||||
background-color: #171717;
|
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: #ffe99d 2px solid;
|
border: #ffe99d 2px solid;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
.warn-window > * {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.tag {
|
.attribute-hp-board {
|
||||||
background: #fce9a7;
|
width: 600px;
|
||||||
|
height: 40px;
|
||||||
|
border: #fff 2px solid;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
.attribute-hp-bg {
|
||||||
|
height: 40px;
|
||||||
|
background-color: #ff5151;
|
||||||
|
position: relative;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attack-a-board {
|
||||||
|
width: 200px;
|
||||||
|
height: 20px;
|
||||||
|
border: #fff 2px solid;
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
.attack-a-bg {
|
||||||
|
height: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
position: relative;
|
||||||
color: #000;
|
color: #000;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -11,6 +11,7 @@ const strengthData = ["31039", "31036"]
|
|||||||
|
|
||||||
// 礼物id和礼物名的对应关系
|
// 礼物id和礼物名的对应关系
|
||||||
const giftData = {
|
const giftData = {
|
||||||
|
"39": "节奏风暴",
|
||||||
"30758": "这个好欸",
|
"30758": "这个好欸",
|
||||||
"30873": "花式夸夸",
|
"30873": "花式夸夸",
|
||||||
"31028": "探索者启航",
|
"31028": "探索者启航",
|
||||||
@ -20,17 +21,34 @@ const giftData = {
|
|||||||
"31044": "情书",
|
"31044": "情书",
|
||||||
"31049": "干杯",
|
"31049": "干杯",
|
||||||
"31053": "告白花束",
|
"31053": "告白花束",
|
||||||
|
"31087": "次元之城",
|
||||||
|
"31088": "为你加冕",
|
||||||
"31122": "星愿水晶球",
|
"31122": "星愿水晶球",
|
||||||
"31164": "粉丝团灯牌",
|
"31164": "粉丝团灯牌",
|
||||||
|
"31538": "超感摩托",
|
||||||
"31588": "星河入梦",
|
"31588": "星河入梦",
|
||||||
|
"31589": "我星永恒",
|
||||||
|
"31591": "星轨列车",
|
||||||
"31883": "璀璨烟火",
|
"31883": "璀璨烟火",
|
||||||
|
"31891": "明灯相伴",
|
||||||
|
"31932": "梦游仙境",
|
||||||
|
"31933": "为你摘星",
|
||||||
|
"32089": "极速超跑",
|
||||||
"32122": "小电视飞船",
|
"32122": "小电视飞船",
|
||||||
|
"32126": "棉花糖",
|
||||||
|
"32199": "爱的抱抱",
|
||||||
"32201": "么么",
|
"32201": "么么",
|
||||||
"32228": "爱的乐章",
|
"32228": "爱的乐章",
|
||||||
|
"32292": "贴贴",
|
||||||
|
"32293": "暖暖爱意",
|
||||||
|
"32360": "璀璨钻石",
|
||||||
|
"32363": "许愿精灵",
|
||||||
"32575": "萌兔火箭",
|
"32575": "萌兔火箭",
|
||||||
"32609": "棒棒糖",
|
"32609": "棒棒糖",
|
||||||
|
"32612": "爱神之箭",
|
||||||
"32692": "落樱缤纷",
|
"32692": "落樱缤纷",
|
||||||
"32734": "快乐时光",
|
"32734": "快乐时光",
|
||||||
|
"32735": "带你出游",
|
||||||
"32758": "爱心雨",
|
"32758": "爱心雨",
|
||||||
"32761": "可爱捏",
|
"32761": "可爱捏",
|
||||||
"32768": "携手同行",
|
"32768": "携手同行",
|
||||||
@ -38,6 +56,7 @@ const giftData = {
|
|||||||
"33032": "干杯工厂",
|
"33032": "干杯工厂",
|
||||||
"33988": "人气票",
|
"33988": "人气票",
|
||||||
"34065": "为你打call",
|
"34065": "为你打call",
|
||||||
|
"34115": "草莓蛋糕",
|
||||||
}
|
}
|
||||||
|
|
||||||
export { waveData, strengthData, giftData }
|
export { waveData, strengthData, giftData }
|
||||||
|
1
src/assets/notyf.min.css
vendored
@ -11,6 +11,8 @@ let softBStrength = ref(0); // B通道软上限
|
|||||||
let followAStrength = ref(false); //跟随A通道软上限
|
let followAStrength = ref(false); //跟随A通道软上限
|
||||||
let followBStrength = ref(false); //跟随B通道软上限
|
let followBStrength = ref(false); //跟随B通道软上限
|
||||||
|
|
||||||
|
const coyoteState = ref(false)
|
||||||
|
|
||||||
let connectionId = ""; // 从接口获取的连接标识符
|
let connectionId = ""; // 从接口获取的连接标识符
|
||||||
let targetWSId = ""; // 发送目标
|
let targetWSId = ""; // 发送目标
|
||||||
let fangdou = 500; //500毫秒防抖
|
let fangdou = 500; //500毫秒防抖
|
||||||
@ -73,6 +75,7 @@ function createCoyoteSocket() {
|
|||||||
console.log("收到targetId: " + msg.targetId + ", msg: " + msg.message);
|
console.log("收到targetId: " + msg.targetId + ", msg: " + msg.message);
|
||||||
qrcodeShow.value = false
|
qrcodeShow.value = false
|
||||||
notyf.success({message: "郊狼连接成功"})
|
notyf.success({message: "郊狼连接成功"})
|
||||||
|
coyoteState.value = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'break':
|
case 'break':
|
||||||
@ -80,6 +83,7 @@ function createCoyoteSocket() {
|
|||||||
return
|
return
|
||||||
console.log("收到断开连接指令")
|
console.log("收到断开连接指令")
|
||||||
notyf.error({ message: "收到断开连接指令" })
|
notyf.error({ message: "收到断开连接指令" })
|
||||||
|
coyoteState.value = false
|
||||||
//location.reload();
|
//location.reload();
|
||||||
break
|
break
|
||||||
case 'error':
|
case 'error':
|
||||||
@ -87,6 +91,7 @@ function createCoyoteSocket() {
|
|||||||
return
|
return
|
||||||
console.log("对方已断开,code:" + msg.message)
|
console.log("对方已断开,code:" + msg.message)
|
||||||
notyf.error({ message: "对方已断开(" + msg.message + ")" })
|
notyf.error({ message: "对方已断开(" + msg.message + ")" })
|
||||||
|
coyoteState.value = false
|
||||||
break
|
break
|
||||||
case 'msg':
|
case 'msg':
|
||||||
const result: { type: string; numbers: number[] }[] = []
|
const result: { type: string; numbers: number[] }[] = []
|
||||||
@ -126,11 +131,13 @@ function createCoyoteSocket() {
|
|||||||
wsConn.onerror = function (event) {
|
wsConn.onerror = function (event) {
|
||||||
console.log("WebSocket连接出错")
|
console.log("WebSocket连接出错")
|
||||||
notyf.error({ message: "WebSocket连接出错" })
|
notyf.error({ message: "WebSocket连接出错" })
|
||||||
|
coyoteState.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
wsConn.onclose = function (event) {
|
wsConn.onclose = function (event) {
|
||||||
console.log("WebSocket连接已关闭")
|
console.log("WebSocket连接已关闭")
|
||||||
notyf.error({ message: "WebSocket连接已关闭" })
|
notyf.error({ message: "WebSocket连接已关闭" })
|
||||||
|
coyoteState.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,31 +146,37 @@ function sendWsMsg(messageObj) {
|
|||||||
messageObj.targetId = targetWSId;
|
messageObj.targetId = targetWSId;
|
||||||
if (!messageObj.hasOwnProperty('type'))
|
if (!messageObj.hasOwnProperty('type'))
|
||||||
messageObj.type = "msg";
|
messageObj.type = "msg";
|
||||||
wsConn.send(JSON.stringify((messageObj)));
|
wsConn.send(JSON.stringify((messageObj)))
|
||||||
}
|
}
|
||||||
|
|
||||||
function addOrIncrease(type, channelIndex, strength) {
|
function addOrIncrease(type, channelIndex, strength) {
|
||||||
// 1 减少一 2 增加一 3 设置到
|
// 1 减少 2 增加 3 设置到
|
||||||
// channel:1-A 2-B
|
// channel:1-A 2-B
|
||||||
// 获取当前频道元素和当前值
|
// 获取当前通道的当前值
|
||||||
let channelStrength = channelIndex === 1 ? channelAStrength.value : channelBStrength.value;
|
let channelStrength = channelIndex === 1 ? channelAStrength.value : channelBStrength.value;
|
||||||
|
|
||||||
// 如果是设置操作
|
// 如果是设置操作
|
||||||
if (type === 3) {
|
if (type === 3) {
|
||||||
channelStrength = strength; //固定为0
|
channelStrength = strength
|
||||||
}
|
}
|
||||||
// 减少一
|
// 减少
|
||||||
else if (type === 1) {
|
else if (type === 1) {
|
||||||
channelStrength = Math.max(channelStrength - strength, 0);
|
channelStrength = Math.max(channelStrength - strength, 0)
|
||||||
}
|
}
|
||||||
// 增加一
|
// 增加
|
||||||
else if (type === 2) {
|
else if (type === 2) {
|
||||||
channelStrength = Math.min(channelStrength + strength, 200);
|
channelStrength = Math.min(channelStrength + strength, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造消息对象并发送
|
// 构造消息对象并发送
|
||||||
const data = { type, strength: channelStrength, message: "set channel", channel: channelIndex };
|
let data = {}
|
||||||
console.log(data)
|
if (type === 3) {
|
||||||
|
data = { type, strength: channelStrength, message: "set channel", channel: channelIndex }
|
||||||
|
} else {
|
||||||
|
// 这里用 type 4 可以自定义增加减小是数值,type 2/3 固定是 1
|
||||||
|
data = { type: 4, message: "strength-" + channelIndex + "+" + (type - 1) + "+" + strength }
|
||||||
|
}
|
||||||
|
|
||||||
sendWsMsg(data);
|
sendWsMsg(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +218,7 @@ function closeCoyoteSocket() {
|
|||||||
}
|
}
|
||||||
wsConn = null
|
wsConn = null
|
||||||
notyf.success( {message: "郊狼连接已断开"} )
|
notyf.success( {message: "郊狼连接已断开"} )
|
||||||
|
coyoteState.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -215,6 +229,7 @@ export {
|
|||||||
sendWaveData,
|
sendWaveData,
|
||||||
addOrIncrease,
|
addOrIncrease,
|
||||||
clearAB,
|
clearAB,
|
||||||
|
coyoteState,
|
||||||
qrcodeSrc,
|
qrcodeSrc,
|
||||||
qrcodeShow,
|
qrcodeShow,
|
||||||
channelAStrength,
|
channelAStrength,
|
||||||
|
@ -8,27 +8,56 @@ let ws: DanmakuWebSocket
|
|||||||
const notyf = new Notyf({ duration: 4000 })
|
const notyf = new Notyf({ duration: 4000 })
|
||||||
|
|
||||||
interface SettingsType {
|
interface SettingsType {
|
||||||
|
version: number;
|
||||||
strengthData: typeof strengthData;
|
strengthData: typeof strengthData;
|
||||||
waveData: typeof waveData;
|
waveData: typeof waveData;
|
||||||
guardLevel: number;
|
guardLevel: number;
|
||||||
|
fansMedal: boolean;
|
||||||
|
}
|
||||||
|
interface TestSettingsType {
|
||||||
|
falloff: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
let settings: Ref<SettingsType> = ref({
|
let settings: Ref<SettingsType> = ref({
|
||||||
|
version: 1,
|
||||||
waveData: waveData,
|
waveData: waveData,
|
||||||
strengthData: strengthData,
|
strengthData: strengthData,
|
||||||
guardLevel: 0
|
guardLevel: 0,
|
||||||
});
|
fansMedal: false
|
||||||
|
})
|
||||||
|
|
||||||
|
let testSettings: Ref<TestSettingsType> = ref({
|
||||||
|
falloff: [0, 0],
|
||||||
|
})
|
||||||
|
|
||||||
if (window.localStorage.getItem("settings")) {
|
if (window.localStorage.getItem("settings")) {
|
||||||
settings.value = JSON.parse(window.localStorage.getItem("settings") || '{}');
|
settings.value = JSON.parse(window.localStorage.getItem("settings") || '{}');
|
||||||
console.log(settings.value)
|
console.log(settings.value)
|
||||||
|
}
|
||||||
|
if (window.localStorage.getItem("test")) {
|
||||||
|
testSettings.value = JSON.parse(window.localStorage.getItem("test") || '{}');
|
||||||
|
console.log(testSettings.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
let waveCounter = ref(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换大航海等级
|
||||||
|
* @description 由于B站返回的大航海等级是(1-总督,2-提督,3-舰长)所以要转换一下方便处理
|
||||||
|
* @param guardLevel
|
||||||
|
*/
|
||||||
|
const transformGuardLevel = (guardLevel: number) => {
|
||||||
|
if (guardLevel == 0) {
|
||||||
|
return 0
|
||||||
|
} else if (guardLevel == 1) {
|
||||||
|
return 3
|
||||||
|
} else if (guardLevel == 2) {
|
||||||
|
return 2
|
||||||
|
} else if (guardLevel == 3) {
|
||||||
|
return 1
|
||||||
} else {
|
} else {
|
||||||
// 如果没有,使用默认值
|
return 0
|
||||||
settings.value = {
|
}
|
||||||
waveData: waveData,
|
|
||||||
strengthData: strengthData,
|
|
||||||
guardLevel: 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,42 +70,33 @@ function createSocket(authBody: string, wssLinks: string[]) {
|
|||||||
...getWebSocketConfig(authBody, wssLinks),
|
...getWebSocketConfig(authBody, wssLinks),
|
||||||
// 收到消息,
|
// 收到消息,
|
||||||
onReceivedMessage: (res) => {
|
onReceivedMessage: (res) => {
|
||||||
console.log("收到"+ res.cmd +"消息:")
|
// 从本地存储中获取设置
|
||||||
//console.log(res.data.uname + "(大航海" +res.data.guard_level + "级):" + res.data.msg)
|
|
||||||
|
|
||||||
// if (res.data.msg == "#UPA1") {
|
|
||||||
// try {
|
|
||||||
// addOrIncrease(2, 1, 1)
|
|
||||||
// notyf.success("A通道强度增加成功")
|
|
||||||
// }
|
|
||||||
// catch (e) {
|
|
||||||
// console.log(e)
|
|
||||||
// notyf.error("A通道强度增加失败")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
settings = window.localStorage.getItem("settings") ? ref(JSON.parse(window.localStorage.getItem("settings") || '{}')) : null
|
settings = window.localStorage.getItem("settings") ? ref(JSON.parse(window.localStorage.getItem("settings") || '{}')) : null
|
||||||
|
|
||||||
if (res.cmd == "LIVE_OPEN_PLATFORM_SEND_GIFT" && res.data.guard_level >= settings.value.guardLevel) {
|
// 粉丝勋章
|
||||||
|
let execute_1 = settings.value.fansMedal ? !!res.data.fans_medal_wearing_status : true
|
||||||
|
|
||||||
|
// 大航海
|
||||||
|
let execute_2 = transformGuardLevel(res.data.guard_level) >= settings.value.guardLevel
|
||||||
|
|
||||||
|
if (res.cmd == "LIVE_OPEN_PLATFORM_SEND_GIFT" && execute_1 && execute_2) {
|
||||||
if (settings && res.data.gift_id.toString() === settings.value.strengthData[0]) {
|
if (settings && res.data.gift_id.toString() === settings.value.strengthData[0]) {
|
||||||
// 牛哇牛哇:加强度1
|
// 加强度
|
||||||
try {
|
try {
|
||||||
console.log("开始操作")
|
addOrIncrease(2, 1, res.data.gift_num)
|
||||||
addOrIncrease(2, 1, 1)
|
addOrIncrease(2, 2, res.data.gift_num)
|
||||||
addOrIncrease(2, 2, 1)
|
notyf.success("收到" + res.data.gift_name + ",强度+" + res.data.gift_num)
|
||||||
console.log("结束操作")
|
|
||||||
notyf.success("收到" + res.data.gift_name + ",强度+1")
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
notyf.error("强度操作失败!")
|
notyf.error("强度操作失败!")
|
||||||
}
|
}
|
||||||
} else if (settings && res.data.gift_id.toString() === settings.value.strengthData[1]) {
|
} else if (settings && res.data.gift_id.toString() === settings.value.strengthData[1]) {
|
||||||
// 小花花:减强度1
|
// 减强度
|
||||||
try {
|
try {
|
||||||
addOrIncrease(1, 1, 1)
|
addOrIncrease(1, 1, res.data.gift_num)
|
||||||
addOrIncrease(1, 2, 1)
|
addOrIncrease(1, 2, res.data.gift_num)
|
||||||
notyf.success("收到" + res.data.gift_name + ",强度-1")
|
notyf.success("收到" + res.data.gift_name + ",强度-" + res.data.gift_num)
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
@ -85,8 +105,14 @@ function createSocket(authBody: string, wssLinks: string[]) {
|
|||||||
} else if(settings && settings.value.waveData[res.data.gift_id]) {
|
} else if(settings && settings.value.waveData[res.data.gift_id]) {
|
||||||
// 其他礼物,发送波形数据
|
// 其他礼物,发送波形数据
|
||||||
try {
|
try {
|
||||||
sendWaveData(5, 5, settings.value.waveData[res.data.gift_id], settings.value.waveData[res.data.gift_id])
|
sendWaveData(5 * res.data.gift_num, 5 * res.data.gift_num, settings.value.waveData[res.data.gift_id], settings.value.waveData[res.data.gift_id])
|
||||||
notyf.success("收到礼物" + res.data.gift_name)
|
notyf.success("收到礼物" + res.data.gift_name + "*"+res.data.gift_num)
|
||||||
|
waveCounter.value++
|
||||||
|
if (waveCounter.value % testSettings.value.falloff[0] == 0 && testSettings.value.falloff[0] > 0) {
|
||||||
|
notyf.success("触发强度衰减")
|
||||||
|
addOrIncrease(1, 1, testSettings.value.falloff[1])
|
||||||
|
addOrIncrease(1, 2, testSettings.value.falloff[1])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
@ -160,4 +186,4 @@ function getWsClient() {
|
|||||||
return ws
|
return ws
|
||||||
}
|
}
|
||||||
|
|
||||||
export { createSocket, destroySocket, getWebSocketConfig, getWsClient }
|
export { createSocket, destroySocket, getWebSocketConfig, getWsClient, waveCounter }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="zh-cn">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|