fix chain modal
Some checks failed
Deploy / deploy (build, debian, 22) (push) Has been cancelled
Deploy / deploy (build:staging, school, 8822) (push) Has been cancelled

This commit is contained in:
2026-04-30 09:42:38 -06:00
parent dd249c8753
commit 375a78b852
6 changed files with 35 additions and 67 deletions

View File

@@ -209,6 +209,11 @@ export const Submission = {
return res.data return res.data
}, },
async getPromptChain(id: string): Promise<PromptRound[]> {
const res = await http.get(`/submission/${id}/prompt-chain`)
return res.data
},
async delete(id: string) { async delete(id: string) {
const res = await http.delete("/submission/" + id) const res = await http.delete("/submission/" + id)
return res.data return res.data

View File

@@ -203,14 +203,13 @@
import { computed, ref, watch } from "vue" import { computed, ref, watch } from "vue"
import { NPopconfirm, NButton } from "naive-ui" import { NPopconfirm, NButton } from "naive-ui"
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import { Prompt } from "../../api" import { Prompt, Submission } from "../../api"
import type { PromptMessage } from "../../utils/type" import type { PromptRound } from "../../utils/type"
import { user, roleSuper } from "../../store/user" import { user, roleSuper } from "../../store/user"
const props = defineProps<{ const props = defineProps<{
show: boolean show: boolean
userId: number submissionId: string
taskId: number
username?: string username?: string
}>() }>()
@@ -219,49 +218,12 @@ const canDelete = computed(() => roleSuper.value || (!!props.username && props.u
defineEmits<{ "update:show": [value: boolean] }>() defineEmits<{ "update:show": [value: boolean] }>()
const loading = ref(false) const loading = ref(false)
const messages = ref<PromptMessage[]>([])
const selectedRound = ref(0) const selectedRound = ref(0)
type ChainRound = Omit<PromptRound, "source"> & {
const rounds = computed(() => {
const result: {
question: string
source: string | null source: string | null
prompt_level: number | null
assistantMsgId: number | null assistantMsgId: number | null
html: string | null
css: string | null
js: string | null
}[] = []
for (const [i, msg] of messages.value.entries()) {
if (msg.role !== "user") continue
let html: string | null = null,
css: string | null = null,
js: string | null = null,
assistantMsgId: number | null = null
for (const reply of messages.value.slice(i + 1)) {
if (reply.role === "user") break
if (reply.role === "assistant") {
assistantMsgId = reply.id
if (reply.code_html) {
html = reply.code_html
css = reply.code_css
js = reply.code_js
} }
break const rounds = ref<ChainRound[]>([])
}
}
result.push({
question: msg.content,
source: msg.source ?? null,
prompt_level: msg.prompt_level ?? null,
assistantMsgId,
html,
css,
js,
})
}
return result
})
async function deleteRound(index: number) { async function deleteRound(index: number) {
const round = rounds.value[index] const round = rounds.value[index]
@@ -291,24 +253,28 @@ const selectedPageHtml = computed(() => {
}) })
async function loadMessages() { async function loadMessages() {
if (!props.userId || !props.taskId) return if (!props.submissionId) return
loading.value = true loading.value = true
messages.value = [] rounds.value = []
selectedRound.value = 0 selectedRound.value = 0
try { try {
messages.value = await Prompt.getMessagesByUserTask( const data = await Submission.getPromptChain(props.submissionId)
props.taskId, rounds.value = data.map((round) => ({
props.userId, ...round,
) source: round.source ?? null,
assistantMsgId: round.assistant_msg_id ?? null,
}))
const last = rounds.value.length - 1 const last = rounds.value.length - 1
if (last >= 0) selectedRound.value = last if (last >= 0) selectedRound.value = last
} catch {
rounds.value = []
} finally { } finally {
loading.value = false loading.value = false
} }
} }
watch( watch(
() => [props.show, props.userId, props.taskId] as const, () => [props.show, props.submissionId] as const,
([visible]) => { ([visible]) => {
if (visible) loadMessages() if (visible) loadMessages()
}, },

View File

@@ -36,7 +36,7 @@ const props = defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
select: [id: string] select: [id: string]
delete: [row: SubmissionOut, parentId: string] delete: [row: SubmissionOut, parentId: string]
"show-chain": [userId: number, taskId: number, username: string] "show-chain": [submissionId: string, username: string]
}>() }>()
const isChallenge = computed(() => props.row.task_type === TASK_TYPE.Challenge) const isChallenge = computed(() => props.row.task_type === TASK_TYPE.Challenge)
@@ -91,7 +91,7 @@ const subColumns = computed((): DataTableColumn<SubmissionOut>[] => [
type: "primary", type: "primary",
onClick: (e: Event) => { onClick: (e: Event) => {
e.stopPropagation() e.stopPropagation()
emit("show-chain", r.userid, r.task_id, r.username) emit("show-chain", r.id, r.username)
}, },
}, },
() => "查看", () => "查看",

View File

@@ -105,8 +105,7 @@
<ChainModal <ChainModal
v-model:show="chainModal" v-model:show="chainModal"
:user-id="chainUserId" :submission-id="chainSubmissionId"
:task-id="chainTaskId"
:username="chainUsername" :username="chainUsername"
/> />
</template> </template>
@@ -159,8 +158,7 @@ const js = computed(() => submission.value.js)
// Modal 状态 // Modal 状态
const codeModal = ref(false) const codeModal = ref(false)
const chainModal = ref(false) const chainModal = ref(false)
const chainUserId = ref<number>(0) const chainSubmissionId = ref<string>("")
const chainTaskId = ref<number>(0)
const chainUsername = ref<string>("") const chainUsername = ref<string>("")
// 展开行 // 展开行
@@ -203,9 +201,8 @@ async function clearAllFlags() {
query.flag = null query.flag = null
} }
function showChain(userId: number, taskId: number, username: string) { function showChain(submissionId: string, username: string) {
chainUserId.value = userId chainSubmissionId.value = submissionId
chainTaskId.value = taskId
chainUsername.value = username chainUsername.value = username
chainModal.value = true chainModal.value = true
} }
@@ -222,7 +219,8 @@ const columns: DataTableColumn<SubmissionOut>[] = [
loading: expandedLoading.has(row.id), loading: expandedLoading.has(row.id),
onSelect: (id) => getSubmissionByID(id), onSelect: (id) => getSubmissionByID(id),
onDelete: (r, parentId) => handleDelete(r, parentId), onDelete: (r, parentId) => handleDelete(r, parentId),
"onShow-chain": (userId, taskId, username) => showChain(userId, taskId, username), "onShow-chain": (submissionId, username) =>
showChain(submissionId, username),
}), }),
}, },
{ {

View File

@@ -68,12 +68,10 @@ export const router = createRouter({
routes, routes,
}) })
router.beforeEach((to, from, next) => { router.beforeEach((to) => {
const isLoggedIn = localStorage.getItem(STORAGE_KEY.LOGIN) === "true" const isLoggedIn = localStorage.getItem(STORAGE_KEY.LOGIN) === "true"
if (to.meta.auth && !isLoggedIn) { if (to.meta.auth && !isLoggedIn) {
loginModal.value = true loginModal.value = true
next(false) return false
} else {
next()
} }
}) })

View File

@@ -200,6 +200,7 @@ export interface PromptRound {
question: string question: string
source: string source: string
prompt_level: number | null prompt_level: number | null
assistant_msg_id?: number | null
html: string | null html: string | null
css: string | null css: string | null
js: string | null js: string | null