feat: 支持按键分离事件与键盘捕获,并优化UI

- 后端与前端新增 keyAction 参数,支持按键按下/抬起独立事件,保持向下兼容
- 前端控制栏支持 pointerdown/pointerup 长按,新增键盘捕获输入框,映射浏览器按键到 Android KeyEvent
- 重构顶栏布局:用户区右置并添加在线指示器、状态文本省略,优化窄屏响应式表现
- 控制栏录制按钮组防拆行,分辨率/帧率选择器自适应收缩,全局样式增强
- 修复 AdminAuthFilter 中 doFilter 被异常捕获导致误返回 401 的问题
- 移除管理后台中用户 admin 角色及相关 UI 与 API
- 更新信令前端环境代理地址,修正路由名称大小写
This commit is contained in:
2026-08-03 11:09:37 +08:00
parent e6ed7c8e3e
commit 78aa3d3c71
16 changed files with 374 additions and 79 deletions

View File

@@ -31,9 +31,6 @@
<el-table-column prop="username" label="用户名" min-width="150">
<template #default="{ row }">
<span class="link-user" @click="openBindings(row)">{{ row.username }}</span>
<el-tag v-if="row.admin" type="danger" size="small" style="margin-left: 6px">
管理员
</el-tag>
<el-tag v-if="row.deviceCount > 0" type="info" size="small" style="margin-left: 6px">
{{ row.deviceCount }} 台设备
</el-tag>
@@ -96,9 +93,6 @@
<el-dropdown-item command="bindings">查看绑定设备</el-dropdown-item>
<el-dropdown-item command="sessions">查看会话</el-dropdown-item>
<el-dropdown-item command="reset">重置密码</el-dropdown-item>
<el-dropdown-item command="admin">
{{ row.admin ? '取消管理员' : '设为管理员' }}
</el-dropdown-item>
<el-dropdown-item command="delete" divided>删除账号</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -118,9 +112,6 @@
<el-form-item label="密码" prop="password">
<el-input v-model="createForm.password" type="password" show-password />
</el-form-item>
<el-form-item label="管理员">
<el-switch v-model="createForm.admin" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="createVisible = false">取消</el-button>
@@ -211,7 +202,6 @@ import {
createUser,
deleteUser,
resetUserPassword,
setUserAdmin,
banUser,
unbanUser,
kickUser,
@@ -249,7 +239,7 @@ watch(statusFilter, load);
// ---------- 添加用户 ----------
const createVisible = ref(false);
const createFormRef = ref<FormInstance>();
const createForm = ref({ username: '', password: '', admin: false });
const createForm = ref({ username: '', password: '' });
const createRules: FormRules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
@@ -262,7 +252,7 @@ const createRules: FormRules = {
};
function openCreate() {
createForm.value = { username: '', password: '', admin: false };
createForm.value = { username: '', password: '' };
createVisible.value = true;
}
@@ -328,19 +318,6 @@ async function handleDelete(row: UserAccountView) {
await load();
}
async function handleToggleAdmin(row: UserAccountView) {
const next = !row.admin;
const ok = await ElMessageBox.confirm(
`确定${next ? '授予' : '取消'}${row.username}」的管理员权限?`,
'权限调整',
{ type: 'warning', confirmButtonText: '确定', cancelButtonText: '取消' },
).catch(() => false);
if (!ok) return;
await setUserAdmin(row.userId, next);
ElMessage.success('权限已更新');
await load();
}
// ---------- 重置密码 ----------
const resetVisible = ref(false);
const newPassword = ref('');
@@ -366,6 +343,9 @@ async function submitReset() {
} else {
ElMessage.error(resp.message || '重置失败');
}
} catch {
// 错误提示已由 request 响应拦截器统一弹出,这里仅吞掉异常,
// 避免未捕获的 Promise rejection并保证弹窗保持打开以便重试。
} finally {
submitting.value = false;
}
@@ -418,7 +398,6 @@ function handleCommand(cmd: string, row: UserAccountView) {
if (cmd === 'bindings') openBindings(row);
else if (cmd === 'sessions') openSessions(row);
else if (cmd === 'reset') openReset(row);
else if (cmd === 'admin') handleToggleAdmin(row);
else if (cmd === 'delete') handleDelete(row);
}