Files
2026-01-18 20:49:14 +08:00

445 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>麻将直播控制面板</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="control-panel">
<h1>麻将直播控制面板</h1>
<!-- 视频源设置 -->
<div class="control-section">
<h3>视频源设置</h3>
<div class="form-group">
<label for="videoSource">视频URL:</label>
<input type="text" id="videoSource" placeholder="输入视频URL"
value="https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_1MB.mp4">
</div>
<button id="setVideoBtn" class="btn">设置视频源</button>
</div>
<!-- 玩家设置 -->
<div class="control-section">
<h3>玩家信息设置</h3>
<table class="player-settings">
<thead>
<tr>
<th>玩家</th>
<th>姓名</th>
<th>分数</th>
<th>颜色</th>
<th>听牌</th>
</tr>
</thead>
<tbody>
<tr>
<td>北家</td>
<td><input type="text" id="playerName0" value="北家"></td>
<td><input type="number" id="playerScore0" value="25000"></td>
<td><input type="color" id="playerColor0" value="#FF6464"></td>
<td><input type="checkbox" id="playerTenpai0"></td>
</tr>
<tr>
<td>东家</td>
<td><input type="text" id="playerName1" value="东家"></td>
<td><input type="number" id="playerScore1" value="25000"></td>
<td><input type="color" id="playerColor1" value="#64FF64"></td>
<td><input type="checkbox" id="playerTenpai1"></td>
</tr>
<tr>
<td>南家</td>
<td><input type="text" id="playerName2" value="南家"></td>
<td><input type="number" id="playerScore2" value="25000"></td>
<td><input type="color" id="playerColor2" value="#6464FF"></td>
<td><input type="checkbox" id="playerTenpai2"></td>
</tr>
<tr>
<td>西家</td>
<td><input type="text" id="playerName3" value="西家"></td>
<td><input type="number" id="playerScore3" value="25000"></td>
<td><input type="color" id="playerColor3" value="#FFFF64"></td>
<td><input type="checkbox" id="playerTenpai3"></td>
</tr>
</tbody>
</table>
<button id="updateAllPlayersBtn" class="btn">更新所有玩家信息</button>
</div>
<!-- 胡牌控制 -->
<div class="control-section">
<h3>胡牌控制</h3>
<div class="form-row">
<div class="form-group">
<label for="winnerSelect">胜者:</label>
<select id="winnerSelect">
<option value="0">北家</option>
<option value="1">东家</option>
<option value="2">南家</option>
<option value="3">西家</option>
</select>
</div>
<div class="form-group">
<label for="hanInput">番数:</label>
<input type="number" id="hanInput" value="2" min="1">
</div>
<div class="form-group">
<label for="fuInput">符数:</label>
<input type="number" id="fuInput" value="30" min="0">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="pointsInput">总点数:</label>
<input type="number" id="pointsInput" value="4000" min="0">
</div>
<div class="form-group">
<label for="isTsumoInput">
<input type="checkbox" id="isTsumoInput"> 自摸
</label>
</div>
</div>
<div class="form-group">
<label for="winTextInput">胡牌描述:</label>
<input type="text" id="winTextInput" placeholder="例如: 三暗刻 自摸">
</div>
<button id="winBtn" class="btn btn-warning">触发胡牌</button>
</div>
<!-- 分数调整 -->
<div class="control-section">
<h3>分数调整</h3>
<div class="form-row">
<div class="form-group">
<label for="adjustPlayerSelect">玩家:</label>
<select id="adjustPlayerSelect">
<option value="0">北家</option>
<option value="1">东家</option>
<option value="2">南家</option>
<option value="3">西家</option>
</select>
</div>
<div class="form-group">
<label for="deltaInput">分数变动:</label>
<input type="number" id="deltaInput" value="1000">
</div>
</div>
<div class="form-row">
<button id="adjustScoreBtn" class="btn">调整分数</button>
<button id="resetScoresBtn" class="btn btn-danger">重置所有分数</button>
</div>
</div>
<!-- 本场与立直棒 -->
<div class="control-section">
<h3>本场与立直棒</h3>
<div class="form-row">
<div class="form-group">
<label for="honbaInput">本场:</label>
<input type="number" id="honbaInput" value="0" min="0">
</div>
<div class="form-group">
<label for="riichiInput">立直棒:</label>
<input type="number" id="riichiInput" value="0" min="0">
</div>
</div>
<button id="setHonbaRiichiBtn" class="btn">设置</button>
</div>
<!-- 样式设置 -->
<div class="control-section">
<h3>样式设置</h3>
<div class="form-row">
<div class="form-group">
<label for="stylePlayerSelect">玩家:</label>
<select id="stylePlayerSelect">
<option value="0">北家</option>
<option value="1">东家</option>
<option value="2">南家</option>
<option value="3">西家</option>
</select>
</div>
<div class="form-group">
<label for="opacityInput">透明度:</label>
<input type="range" id="opacityInput" min="0.1" max="1" step="0.1" value="0.6">
<span id="opacityValue">0.6</span>
</div>
<div class="form-group">
<label for="fontSizeInput">字体大小:</label>
<input type="number" id="fontSizeInput" min="12" max="32" value="18">
</div>
</div>
<button id="setStyleBtn" class="btn">应用样式</button>
</div>
<!-- 测试按钮 -->
<div class="control-section">
<h3>测试功能</h3>
<button id="openOverlayBtn" class="btn">打开叠加层</button>
<button id="testWinBtn" class="btn btn-warning">测试胡牌动画</button>
</div>
</div>
<script>
// 全局变量
let overlayWindow = null;
const defaultOpacity = 0.6;
// DOM元素
const elements = {
// 视频设置
videoSource: document.getElementById('videoSource'),
setVideoBtn: document.getElementById('setVideoBtn'),
// 玩家设置
updateAllPlayersBtn: document.getElementById('updateAllPlayersBtn'),
// 胡牌控制
winnerSelect: document.getElementById('winnerSelect'),
hanInput: document.getElementById('hanInput'),
fuInput: document.getElementById('fuInput'),
pointsInput: document.getElementById('pointsInput'),
isTsumoInput: document.getElementById('isTsumoInput'),
winTextInput: document.getElementById('winTextInput'),
winBtn: document.getElementById('winBtn'),
// 分数调整
adjustPlayerSelect: document.getElementById('adjustPlayerSelect'),
deltaInput: document.getElementById('deltaInput'),
adjustScoreBtn: document.getElementById('adjustScoreBtn'),
resetScoresBtn: document.getElementById('resetScoresBtn'),
// 本场与立直棒
honbaInput: document.getElementById('honbaInput'),
riichiInput: document.getElementById('riichiInput'),
setHonbaRiichiBtn: document.getElementById('setHonbaRiichiBtn'),
// 样式设置
stylePlayerSelect: document.getElementById('stylePlayerSelect'),
opacityInput: document.getElementById('opacityInput'),
opacityValue: document.getElementById('opacityValue'),
fontSizeInput: document.getElementById('fontSizeInput'),
setStyleBtn: document.getElementById('setStyleBtn'),
// 测试按钮
openOverlayBtn: document.getElementById('openOverlayBtn'),
testWinBtn: document.getElementById('testWinBtn')
};
// 初始化
function init() {
setupEventListeners();
}
// 设置事件监听
function setupEventListeners() {
// 视频设置
elements.setVideoBtn.addEventListener('click', setVideoSource);
// 玩家设置
elements.updateAllPlayersBtn.addEventListener('click', updateAllPlayers);
// 胡牌控制
elements.winBtn.addEventListener('click', triggerWin);
// 分数调整
elements.adjustScoreBtn.addEventListener('click', adjustScore);
elements.resetScoresBtn.addEventListener('click', resetScores);
// 本场与立直棒
elements.setHonbaRiichiBtn.addEventListener('click', setHonbaRiichi);
// 样式设置
elements.opacityInput.addEventListener('input', updateOpacityValue);
elements.setStyleBtn.addEventListener('click', setStyle);
// 测试按钮
elements.openOverlayBtn.addEventListener('click', openOverlay);
elements.testWinBtn.addEventListener('click', testWin);
// 听牌复选框事件
for (let i = 0; i < 4; i++) {
document.getElementById(`playerTenpai${i}`).addEventListener('change', (e) => {
sendEvent({
event: 'set_tenpai',
player_index: i,
is_tenpai: e.target.checked
});
});
}
}
// 打开叠加层窗口
function openOverlay() {
if (overlayWindow && !overlayWindow.closed) {
overlayWindow.focus();
} else {
overlayWindow = window.open('index.html', '麻将直播叠加层', 'width=1280,height=720');
}
}
// 发送事件到叠加层
function sendEvent(event) {
console.log('发送事件:', event);
// 发送到打开的窗口
if (overlayWindow && !overlayWindow.closed) {
overlayWindow.postMessage(event, '*');
}
// 同时发送到当前窗口(如果叠加层在同一个窗口)
window.postMessage(event, '*');
}
// 设置视频源
function setVideoSource() {
sendEvent({
event: 'set_video_source',
src: elements.videoSource.value
});
}
// 更新所有玩家信息
function updateAllPlayers() {
for (let i = 0; i < 4; i++) {
const name = document.getElementById(`playerName${i}`).value;
const score = parseInt(document.getElementById(`playerScore${i}`).value) || 0;
const color = document.getElementById(`playerColor${i}`).value;
const isTenpai = document.getElementById(`playerTenpai${i}`).checked;
// 将hex颜色转换为带透明度的rgba
const rgbaColor = hexToRgba(color, defaultOpacity);
sendEvent({
event: 'update_player',
player_index: i,
name: name,
score: score,
color: rgbaColor,
is_tenpai: isTenpai
});
}
}
// 触发胡牌
function triggerWin() {
const winner = parseInt(elements.winnerSelect.value);
const han = parseInt(elements.hanInput.value);
const fu = parseInt(elements.fuInput.value);
const points = parseInt(elements.pointsInput.value);
const isTsumo = elements.isTsumoInput.checked;
const text = elements.winTextInput.value;
// 确定输家
let losers = [];
if (isTsumo) {
// 自摸时,其他三人为输家
losers = [0, 1, 2, 3].filter(i => i !== winner);
} else {
// 默认为下家放铳,可根据实际情况修改
losers = [(winner + 1) % 4];
}
sendEvent({
event: 'win',
winner: winner,
losers: losers,
han: han,
fu: fu,
points: points,
is_tsumo: isTsumo,
text: text
});
}
// 调整分数
function adjustScore() {
const playerIndex = parseInt(elements.adjustPlayerSelect.value);
const delta = parseInt(elements.deltaInput.value);
sendEvent({
event: 'adjust_score',
player_index: playerIndex,
delta: delta
});
}
// 重置所有分数
function resetScores() {
if (confirm('确定要重置所有玩家分数为25000吗')) {
for (let i = 0; i < 4; i++) {
document.getElementById(`playerScore${i}`).value = 25000;
sendEvent({
event: 'update_player',
player_index: i,
score: 25000
});
}
}
}
// 设置本场与立直棒
function setHonbaRiichi() {
const honba = parseInt(elements.honbaInput.value);
const riichiSticks = parseInt(elements.riichiInput.value);
sendEvent({
event: 'set_honba_riichi',
honba: honba,
riichi_sticks: riichiSticks
});
}
// 更新透明度显示值
function updateOpacityValue() {
elements.opacityValue.textContent = elements.opacityInput.value;
}
// 设置样式
function setStyle() {
const playerIndex = parseInt(elements.stylePlayerSelect.value);
const opacity = parseFloat(elements.opacityInput.value);
const fontSize = parseInt(elements.fontSizeInput.value);
sendEvent({
event: 'set_style',
player_index: playerIndex,
opacity: opacity,
font_size: fontSize
});
}
// 测试胡牌动画
function testWin() {
sendEvent({
event: 'win',
winner: 1,
losers: [0, 2, 3],
han: 3,
fu: 40,
points: 8000,
is_tsumo: true,
text: '三暗刻 自摸'
});
}
// 辅助函数将hex颜色转换为rgba
function hexToRgba(hex, alpha) {
// 移除#号
hex = hex.replace('#', '');
// 解析RGB值
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
// 初始化控制面板
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>