fix(admin): 写操作不再被实时连接状态拦截
原来 canWrite 依赖 realtimeStatus === 'online',WS 一断(服务端重启、网络瞬断、 以及之前那个 1008 停重连的 bug)整个管理端就变只读:基础数据的「保存全部」、 录入、发布、积分调整、大屏控制全部按钮变灰,且只是变淡、看不出原因。 写路径本来就是 HTTP,服务端会做完整校验,所以: - stores/event.ts 的 canWrite 恒为 true(保留签名,角色判断由各页面叠加 auth.readOnly) - useBaseData.canWrite 简化为 !auth.readOnly - 顶部「连接中断」的提示改为「数据可能不是最新」,不再声称写操作停用 - 文档同步:FAQ 与使用手册区分「示例数据」(改动只在界面)与「连接中断」(照常提交) 新增 web/src/admin/tests/base-data.test.ts 锁住该行为(离线可写 / 访客不可写)。
This commit is contained in:
1 parent
0c9a6b6a27
commit
c2696e768e
6 files changed
+42
-9
No files matched your search
@@ -272,7 +272,6 @@ export interface BaseDataController {
|
||||
|
||||
export function useBaseData(): BaseDataController {
|
||||
const auth = useAuthStore()
|
||||
const shared = useEventStore()
|
||||
|
||||
return {
|
||||
teams,
|
||||
@@ -288,8 +287,8 @@ export function useBaseData(): BaseDataController {
|
||||
mockLabel: computed(() =>
|
||||
baseDataFallback.value || mockMode.value ? `示例数据(${mockReason.value ?? '服务端未就绪'})` : null,
|
||||
),
|
||||
// 示例数据模式允许本地写入,否则整页只能看不能改,交互无从验证。
|
||||
canWrite: computed(() => !auth.readOnly && (baseDataFallback.value || shared.canWrite)),
|
||||
// 写权限只看角色:写操作走 HTTP、服务端会做完整校验,实时连接断线不该让整页变只读。
|
||||
canWrite: computed(() => !auth.readOnly),
|
||||
load,
|
||||
loadEventDetail,
|
||||
selectEvent,
|
||||
|
||||
@@ -85,7 +85,7 @@ const connection = computed(() => {
|
||||
return { tone: 'success', text: '实时在线', hint: data.serverVersion === null ? '' : `版本 ${data.serverVersion}` }
|
||||
}
|
||||
if (data.realtimeStatus === 'connecting') return { tone: 'info', text: '连接中…', hint: '' }
|
||||
return { tone: 'error', text: '连接中断', hint: '写操作已停用' }
|
||||
return { tone: 'error', text: '连接中断', hint: '数据可能不是最新' }
|
||||
})
|
||||
|
||||
async function refresh(): Promise<void> {
|
||||
|
||||
@@ -44,10 +44,13 @@ export const useEventStore = defineStore('admin-event', () => {
|
||||
)
|
||||
const online = computed(() => realtimeStatus.value === 'online')
|
||||
/**
|
||||
* 写操作门槛:真实后端需实时在线;示例数据模式允许本地写入以便走通交互。
|
||||
* 登录态由 auth store 叠加判断,这里只管连接。
|
||||
* 写操作门槛:写路径是 HTTP,服务端会做完整校验,因此这里恒为 true;
|
||||
* 角色判断由各页面叠加 `auth.readOnly` 完成。
|
||||
*
|
||||
* 曾经写成「实时在线才可写」,结果 WS 一断(服务端重启、网络瞬断)整站变只读,
|
||||
* 现场代价太大;实时连接状态只用于顶部「连接中断」提示,不再拦截写操作。
|
||||
*/
|
||||
const canWrite = computed(() => mockMode.value || realtimeStatus.value === 'online')
|
||||
const canWrite = computed(() => true)
|
||||
|
||||
function applySnapshot(snapshot: SnapshotMessage): void {
|
||||
settings.value = snapshot.settings
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import type { CurrentUser } from '@/shared'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { useEventStore } from '../stores/event'
|
||||
import { useBaseData } from '../components/baseData/useBaseData'
|
||||
|
||||
// 写权限只看角色:实时连接断开(服务端重启、网络瞬断)不得让整页变只读。
|
||||
// 曾经 canWrite 依赖 realtimeStatus === 'online',WS 一断连「保存全部」都是灰的。
|
||||
test('实时连接离线时仍可写,只读访客不可写', () => {
|
||||
setActivePinia(createPinia())
|
||||
const auth = useAuthStore()
|
||||
const event = useEventStore()
|
||||
const data = useBaseData()
|
||||
|
||||
assert.equal(event.realtimeStatus, 'idle', '未连接时状态应为 idle')
|
||||
assert.equal(event.canWrite, true, '离线不应拦截写操作')
|
||||
assert.equal(data.canWrite.value, false, '未登录(访客)不可写')
|
||||
|
||||
auth.user = { id: 1, username: 'admin', displayName: '管理员', role: 'admin' } as unknown as CurrentUser
|
||||
assert.equal(auth.readOnly, false)
|
||||
assert.equal(data.canWrite.value, true, '登录后即使实时连接离线也应可写')
|
||||
|
||||
auth.user = null
|
||||
assert.equal(data.canWrite.value, false, '退出后回到只读访客')
|
||||
})
|
||||
Reference in new issue
Block a user