Skip to content

Commit

Permalink
feat: the history page supports clearing invalid records
Browse files Browse the repository at this point in the history
  • Loading branch information
WhiteMinds committed Mar 1, 2024
1 parent dd5ff36 commit 733a352
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 5 deletions.
6 changes: 6 additions & 0 deletions packages/http-server/src/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ export function removeRecord(id: RecordModel['id']): void {
scheduleSave()
}

export function removeRecords(ids: RecordModel['id'][]): void {
assertDBReady(db)
db.data.records = db.data.records.filter((record) => !ids.includes(record.id))
scheduleSave()
}

export function updateRecordStopTime(props: Required<Pick<RecordModel, 'id' | 'stopTimestamp'>>): void {
assertDBReady(db)
// TODO: 性能有问题的话可以在 insert 时做个索引表
Expand Down
8 changes: 8 additions & 0 deletions packages/http-server/src/routes/api_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ export namespace API {
export type Resp = Omit<RecorderManagerCreateOpts, 'providers'>
}

export namespace clearInvalidRecords {
export interface Args {
recorderId?: Recorder['id']
}

export type Resp = number
}

export namespace getRecords {
export interface Args extends PagedArgs {
recorderId?: Recorder['id']
Expand Down
13 changes: 13 additions & 0 deletions packages/http-server/src/routes/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ router.route('/records').get(async (req, res) => {
res.json({ payload: await getRecords({ recorderId, page, pageSize }) })
})

router.route('/records/clear_invalid').post(async (req, res) => {
const { recorderId } = req.body
if (recorderId != null) {
assertStringType(recorderId)
}

const records = await getRecords({ recorderId, page: 1, pageSize: 1e10 })
const invalidIds = records.items.filter((item) => !item.isFileExists).map((item) => item.id)
db.removeRecords(invalidIds)

res.json({ payload: invalidIds.length })
})

router.route('/records/:id').get(async (req, res) => {
const { id } = req.params
res.json({ payload: getRecord({ id }) })
Expand Down
6 changes: 6 additions & 0 deletions packages/web/src/services/LARServerService/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ async function getManagerDefault(args: API.getManagerDefault.Args): Promise<API.
return resp.data.payload
}

async function clearInvalidRecords(args: API.clearInvalidRecords.Args): Promise<API.clearInvalidRecords.Resp> {
const resp = await requester.post<{ payload: API.clearInvalidRecords.Resp }>('/records/clear_invalid', args)
return resp.data.payload
}

async function getRecords(args: API.getRecords.Args): Promise<API.getRecords.Resp> {
const resp = await requester.get<{ payload: API.getRecords.Resp }>('/records', {
params: args,
Expand Down Expand Up @@ -135,6 +140,7 @@ export const LARServerService = {
updateManager,
resolveChannel,
getManagerDefault,
clearInvalidRecords,
getRecords,
getRecord,
getRecordExtraData,
Expand Down
43 changes: 38 additions & 5 deletions packages/web/src/views/Records/index.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
<template>
<v-card class="m-4" flat>
<v-card-title class="my-2 flex items-center justify-between gap-4">
<div>
<div class="flex items-center">
<v-icon icon="mdi-arrow-left" size="24" class="mr-2" @click="$router.back" />
录像历史
<span>录像历史</span>
<v-btn class="ml-4" size="small" variant="tonal" @click="clearInvalidWarnVisible = true">清理无效记录</v-btn>

<v-dialog v-model="clearInvalidWarnVisible">
<v-card title="注意" text="这将移除所有视频文件已被删除的记录,包括搜索过滤之前的文件。">
<template v-slot:actions>
<v-spacer></v-spacer>

<v-btn v-if="!requestingClearInvalid" @click="clearInvalidWarnVisible = false">取消</v-btn>
<v-btn @click="clearInvalid" :loading="requestingClearInvalid">确认</v-btn>
</template>
</v-card>
</v-dialog>
</div>

<v-text-field
Expand All @@ -17,6 +29,8 @@
/>
</v-card-title>

<v-alert class="m-4" type="success" v-model="alert" :text="alert" closable></v-alert>

<div v-if="loading" class="text-center p-4">
<v-progress-circular indeterminate color="primary" />
</div>
Expand Down Expand Up @@ -115,21 +129,26 @@ const recorderId = route.name === RouteNames.RecorderRecords ? String(route.para
type Record = ClientRecord & { generatingSRT?: boolean }
const records = ref<Record[]>([])
const loading = ref(true)
const clearInvalidWarnVisible = ref(false)
const requestingClearInvalid = ref(false)
const alert = ref<false | string>(false)
const search = ref('')
useEffectInLifecycle(() => {
return InteractionService.onEscapeWhenBody(() => router.back())
})
onMounted(async () => {
const refreshRecords = async () => {
loading.value = true
const res = await LARServerService.getRecords({
recorderId,
page: 1,
pageSize: 9999,
// TODO: 暂时全部拉下来做本地分页
pageSize: 1e10,
})
loading.value = false
records.value = [...res.items].reverse()
})
}
const genSRT = async (record: Record) => {
if (record.generatingSRT) return
Expand All @@ -142,6 +161,20 @@ const genSRT = async (record: Record) => {
}
}
const clearInvalid = async () => {
requestingClearInvalid.value = true
try {
const count = await LARServerService.clearInvalidRecords({ recorderId })
alert.value = `共 ${count} 条无效记录被移除`
} finally {
requestingClearInvalid.value = false
}
clearInvalidWarnVisible.value = false
refreshRecords()
}
onMounted(refreshRecords)
function formatInterval(record: ClientRecord) {
const stopTimestamp = record.stopTimestamp ?? record.startTimestamp
const time = stopTimestamp - record.startTimestamp
Expand Down

0 comments on commit 733a352

Please sign in to comment.