Files
chongming-web/src/composables/useAdminAuth.ts
T
chakcy 5b91548246 add: 邦泽参数配置页(音柱 / 告警结构化配置)
新增「参数配置」页(/config),按客户使用场景而非插件边界组织
aibox_sophon_adapter 与 ip_sound_column 的配置:

- IP 音柱报警:音柱设备 IP(属 ip_sound_column)+ 启用/音量/播报文案
  映射(属 aibox_sophon_adapter);两个插件在同一页配完,保存时按归属
  分别下发并重启对应副本。
- 告警与联动:告警转发、心跳与离线、告警留存、豆包分析、IN2 联动。
- 未开放数据库、数据目录、MediaMTX、MQTT 通道等部署类配置,页面脚注
  说明;仍可用 Worker 管理的原始编辑器维护。

关键实现约束(见 src/config/configEdits.ts):
- 后端对 [workers.config] 只做顶层浅合并,被改动的嵌套节必须整节提交,
  否则改一个音量会清掉同级的 enabled/tts(已用真实接口复现)。
- 区块开关默认值取自插件代码默认值,避免「配置里没有该键时开关显示为关
  且被判为已改动」而在改其它字段时误关功能。
- 数值字段留空直接拦下,不把 NaN 下发成 null 触发插件侧回滚。

其他:
- tts 映射的违规类型候选来自历史告警记录(list_alarms),手写拼错不易察觉。
- 登录态抽成 useAdminAuth 与 Worker 管理页共用,token 互通。
- Worker 管理弹窗对这两个插件给出跳转提示,原始编辑器保留为应急通道。
2026-09-18 10:00:32 +08:00

75 lines
2.5 KiB
TypeScript
Raw 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.
/**
* 管理端登录状态(跨页面共享单例)。
*
* 参数配置页与 Worker 管理页共用同一份 token(localStorage 的 cm_admin_token),
* 在任一页面登录后另一页面无需重复登录。抽成模块级单例而非 Pinia store,
* 避免为这点状态引入额外样板。
*/
import { computed, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { login, parseJwt, TOKEN_KEY, type AuthUser } from '@/api/workerAdmin'
const token = ref(localStorage.getItem(TOKEN_KEY) || '')
const currentUser = ref<AuthUser | null>(null)
const username = ref('')
const password = ref('')
const logging = ref(false)
/** 从持久化 token 恢复身份(进入页面时调用;权限校验仍以后端为准) */
export function restoreAuth(): AuthUser | null {
const t = token.value.trim()
currentUser.value = t ? parseJwt(t) : null
return currentUser.value
}
export function useAdminAuth() {
const isLoggedIn = computed(() => !!token.value.trim())
/**
* 登录并领取管理 Token。
* @returns 登录成功时的用户信息;失败返回 null(已弹出提示)。
*/
const doLogin = async (): Promise<AuthUser | null> => {
const name = username.value.trim()
if (!name || !password.value) {
ElMessage.warning('请输入用户名和密码')
return null
}
logging.value = true
try {
const data = await login(name, password.value)
// 后端登录失败仍返回 HTTP 200,仅 result=fail + 空 token
if (data.result !== 'success' || !data.token) {
ElMessage.error(`登录失败:${data.message || '用户名或密码错误'}`)
return null
}
token.value = data.token
localStorage.setItem(TOKEN_KEY, data.token)
username.value = ''
password.value = ''
const info = parseJwt(data.token)
currentUser.value = info
ElMessage.success(`登录成功:${(info?.username || '').trim() || '未知用户'}`)
if (!info?.is_superuser) {
ElMessage.error('权限不足:仅超级管理员可管理配置,操作将被拒绝')
return null
}
return info
} catch (e: any) {
ElMessage.error(`登录失败:${e.message}`)
return null
} finally {
logging.value = false
}
}
const logout = () => {
localStorage.removeItem(TOKEN_KEY)
token.value = ''
currentUser.value = null
ElMessage.success('已退出登录')
}
return { token, currentUser, username, password, logging, isLoggedIn, doLogin, logout }
}