wib / index.html
izuemon's picture
Update index.html
df25bc9 verified
Raw
History Blame Contribute Delete
9.86 kB
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>スタディーサプリ</title>
<script src="https://cdn.jsdelivr.net/npm/eruda@3.4.3/eruda.min.js"></script><script>eruda.init();</script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<style>
body {
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
background-color: #f5f5f5;
}
.toolbar {
background-color: #01579B;
color: white;
padding: 8px;
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.client-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 12px;
padding: 16px;
}
.client-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
overflow: hidden;
cursor: pointer;
transition: all 0.2s;
}
.client-card.selected {
background-color: #e3f2fd;
border: 2px solid #2196f3;
}
.client-header {
background-color: #f0f0f0;
padding: 8px;
font-weight: bold;
border-bottom: 1px solid #ddd;
display: flex;
justify-content: space-between;
}
.client-body {
padding: 8px;
text-align: center;
}
.client-status {
font-size: 12px;
margin-top: 8px;
}
.video-preview {
width: 100%;
background: #000;
border-radius: 4px;
}
button {
background-color: #01579B;
color: white;
border: none;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
margin: 2px;
}
button:disabled {
background-color: #9e9e9e;
cursor: not-allowed;
}
.lock-dialog, .settings-dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.2);
z-index: 1000;
width: 300px;
}
.overlay {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 999;
}
.hidden {
display: none;
}
.status-badge {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 6px;
}
.status-online { background-color: #4caf50; }
.status-offline { background-color: #9e9e9e; }
.status-wait { background-color: #ff9800; }
.lock-info {
font-size: 12px;
margin-top: 4px;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-main>
<div class="toolbar">
<div>
<input type="text" v-model="teacherEmail" placeholder="教師メールアドレス" style="width:200px;">
<input type="text" v-model="className" placeholder="クラス名">
<button @click="initializeSystem">初期化・接続開始</button>
</div>
<div style="margin-left: auto;">
選択中: {{ selectedCount }}台
<button @click="allSelect">全選択</button>
<button @click="allUnselect">全解除</button>
<button @click="refreshStatus">状態更新</button>
</div>
</div>
<div class="toolbar" style="background-color:#e0e0e0; color:black;">
<button @click="startDesktopShare" :disabled="!canShare">画面提示開始</button>
<button @click="stopDesktopShare">画面提示停止</button>
<button @click="openLockDialog">ロック</button>
<button @click="unlock">ロック解除</button>
<button @click="fetchDeviceInfo">デバイス情報取得</button>
<span style="margin-left:auto;">状態モード
<label><input type="radio" value="status" v-model="dispMode"> ステータス</label>
<label><input type="radio" value="desktop" v-model="dispMode"> 画面表示</label>
</span>
</div>
<div class="client-grid">
<div v-for="client in clients" :key="client.mailAddress"
class="client-card" :class="{selected: client.selected}"
@click="toggleSelect(client)">
<div class="client-header">
<span>{{ client.dispName || client.mailAddress.split('@')[0] }}</span>
<span>
<span class="status-badge" :class="statusClass(client)"></span>
{{ statusText(client) }}
</span>
</div>
<div class="client-body">
<div v-if="dispMode === 'desktop' && client.p2p === 'successful' && client.power && client.joinState === 'consent'">
<video :id="'video_'+client.mailAddress" autoplay muted class="video-preview" style="width:100%; height:auto;"></video>
</div>
<div v-else>
<div v-if="client.activeTab && client.activeTab.title">
<img :src="client.activeTab.favicon" width="32" height="32" style="vertical-align: middle;">
{{ client.activeTab.title.substring(0,30) }}
</div>
<div v-else-if="!client.power">電源OFF</div>
<div v-else-if="client.joinState === 'wait'">参加待ち</div>
<div v-else-if="client.joinState === 'refusal'">参加拒否</div>
<div v-else-if="client.p2p === 'unknown'">接続確認中</div>
<div v-else>情報なし</div>
</div>
<div class="client-status">
{{ client.pVer ? 'Ver:'+client.pVer : '' }} {{ client.battery.level ? '🔋'+client.battery.level+'%' : '' }}
<span v-if="client.mouseLock">🔒</span>
<span v-if="client.urlLimit">🌐制限</span>
</div>
</div>
</div>
</div>
<!-- ロックダイアログ -->
<div v-if="showLockDlg" class="overlay" @click.self="showLockDlg=false"></div>
<div v-if="showLockDlg" class="lock-dialog">
<h3>ロック設定</h3>
<div>
<label><input type="radio" value="image" v-model="lockType"> 画像ロック</label>
<label><input type="radio" value="text" v-model="lockType"> テキストロック</label>
</div>
<div v-if="lockType === 'image'">
<select v-model="lockImage">
<option value="image1">ロック画面1</option>
<option value="image2">ロック画面2</option>
<option value="image3">ロック画面3</option>
</select>
</div>
<div v-else>
<input type="text" v-model="lockText" placeholder="表示文字">
文字色: <input type="color" v-model="lockFColor">
背景色: <input type="color" v-model="lockBColor">
</div>
<div>
<label><input type="checkbox" v-model="timeLimited"> 時間指定</label>
<div v-if="timeLimited">
<select v-model="lockLimitedTipe">
<option value="rdoLockTime">経過時間</option>
<option value="rdoLockMoment">時刻指定</option>
</select>
<input v-if="lockLimitedTipe === 'rdoLockTime'" type="text" v-model="lockTime" placeholder="HH:MM:SS">
<input v-else type="text" v-model="lockMoment" placeholder="HH:MM:SS">
</div>
</div>
<div style="margin-top:16px;">
<button @click="executeLock">実行</button>
<button @click="showLockDlg=false">キャンセル</button>
</div>
</div>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.22.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.22.0/firebase-database-compat.js"></script>
<script src="firebase-config.js"></script>
<script src="main.js"></script>
</body>
</html>