+
题目
{{ selectedRecord.question }}
+ >{{ selectedRecord.question }}
选项
-
{{ selectedRecord.options || "-" }}
+
+
+
+ {{ line.text }}
+
+
+
-
+
答案
{{ selectedRecord.answer }}
+ >{{ selectedRecord.answer }}
diff --git a/app/components/dashboard/QaRecordsTable.vue b/app/components/dashboard/QaRecordsTable.vue
index ccde928..7db500a 100644
--- a/app/components/dashboard/QaRecordsTable.vue
+++ b/app/components/dashboard/QaRecordsTable.vue
@@ -5,6 +5,7 @@ import { storeToRefs } from "pinia";
import TableCom from "@/components/Table/TableCom.vue";
import type { TableColumn } from "@/components/Table/type";
+import TooltipCom from "@/components/TooltipCom.vue";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
@@ -21,12 +22,12 @@ import {
SelectTrigger,
SelectValue
} from "@/components/ui/select";
-import type { IQaRecord } from "@/interfaces";
import {
DASHBOARD_PAGE_SIZE_OPTIONS,
QUESTION_TYPE_LABELS,
useAnswerStore
} from "@/stores/answer";
+import { getOptionLines } from "@/utils";
const answerStore = useAnswerStore();
const {
@@ -79,11 +80,6 @@ const columns = computed
(() => [
const getQuestionTypeLabel = (type: string) => {
return QUESTION_TYPE_LABELS[type] || type || "自动判断";
};
-
-/** 空选项统一展示占位,不在表格中撑开大段空白 */
-const displayOptions = (record: IQaRecord) => {
- return record.options || "-";
-};
@@ -148,12 +144,49 @@ const displayOptions = (record: IQaRecord) => {
-
- {{ displayOptions(row) }}
-
+
+
+
+
+
+
+ {{ line.text }}
+
+
+ -
+
+
+
+
diff --git a/app/components/ui/popover/Popover.vue b/app/components/ui/popover/Popover.vue
new file mode 100644
index 0000000..a3fe9ac
--- /dev/null
+++ b/app/components/ui/popover/Popover.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/PopoverAnchor.vue b/app/components/ui/popover/PopoverAnchor.vue
new file mode 100644
index 0000000..e96a121
--- /dev/null
+++ b/app/components/ui/popover/PopoverAnchor.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/PopoverContent.vue b/app/components/ui/popover/PopoverContent.vue
new file mode 100644
index 0000000..a60d609
--- /dev/null
+++ b/app/components/ui/popover/PopoverContent.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/PopoverDescription.vue b/app/components/ui/popover/PopoverDescription.vue
new file mode 100644
index 0000000..4c7968a
--- /dev/null
+++ b/app/components/ui/popover/PopoverDescription.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/PopoverHeader.vue b/app/components/ui/popover/PopoverHeader.vue
new file mode 100644
index 0000000..fe1338d
--- /dev/null
+++ b/app/components/ui/popover/PopoverHeader.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/PopoverTitle.vue b/app/components/ui/popover/PopoverTitle.vue
new file mode 100644
index 0000000..e1d5235
--- /dev/null
+++ b/app/components/ui/popover/PopoverTitle.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/PopoverTrigger.vue b/app/components/ui/popover/PopoverTrigger.vue
new file mode 100644
index 0000000..0d41065
--- /dev/null
+++ b/app/components/ui/popover/PopoverTrigger.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/popover/index.ts b/app/components/ui/popover/index.ts
new file mode 100644
index 0000000..1633776
--- /dev/null
+++ b/app/components/ui/popover/index.ts
@@ -0,0 +1,7 @@
+export { default as Popover } from './Popover.vue'
+export { default as PopoverAnchor } from './PopoverAnchor.vue'
+export { default as PopoverContent } from './PopoverContent.vue'
+export { default as PopoverDescription } from './PopoverDescription.vue'
+export { default as PopoverHeader } from './PopoverHeader.vue'
+export { default as PopoverTitle } from './PopoverTitle.vue'
+export { default as PopoverTrigger } from './PopoverTrigger.vue'
diff --git a/app/components/ui/tooltip/Tooltip.vue b/app/components/ui/tooltip/Tooltip.vue
new file mode 100644
index 0000000..a531d43
--- /dev/null
+++ b/app/components/ui/tooltip/Tooltip.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/tooltip/TooltipContent.vue b/app/components/ui/tooltip/TooltipContent.vue
new file mode 100644
index 0000000..f9c70a6
--- /dev/null
+++ b/app/components/ui/tooltip/TooltipContent.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/ui/tooltip/TooltipProvider.vue b/app/components/ui/tooltip/TooltipProvider.vue
new file mode 100644
index 0000000..8cc971f
--- /dev/null
+++ b/app/components/ui/tooltip/TooltipProvider.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/tooltip/TooltipTrigger.vue b/app/components/ui/tooltip/TooltipTrigger.vue
new file mode 100644
index 0000000..59f16b6
--- /dev/null
+++ b/app/components/ui/tooltip/TooltipTrigger.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/app/components/ui/tooltip/index.ts b/app/components/ui/tooltip/index.ts
new file mode 100644
index 0000000..5ab9653
--- /dev/null
+++ b/app/components/ui/tooltip/index.ts
@@ -0,0 +1,4 @@
+export { default as Tooltip } from './Tooltip.vue'
+export { default as TooltipContent } from './TooltipContent.vue'
+export { default as TooltipProvider } from './TooltipProvider.vue'
+export { default as TooltipTrigger } from './TooltipTrigger.vue'
diff --git a/app/utils/format.ts b/app/utils/format.ts
new file mode 100644
index 0000000..39ae075
--- /dev/null
+++ b/app/utils/format.ts
@@ -0,0 +1,36 @@
+// app/utils/format.ts - 文本格式化工具
+
+/**
+ * 将选项字符串从"字母在上、内容在下"的换行格式合并为"字母. 内容"的单行格式。
+ * 例如:
+ * 输入:`A.\n错\nB.\n对`
+ * 输出:`A. 错\nB. 对`
+ */
+export function formatOptions(options: string): string {
+ // 匹配类似 "A." 开头的选项标记,将其后紧跟的换行内容合并到同一行
+ return options.replace(/^([A-Za-z]\.)\s*\n\s*/gm, "$1 ");
+}
+
+/**
+ * 将选项字符串拆分为逐行结构,标记哪些行是正确答案。
+ * answer 按 # 分隔(多选),与选项正文做等值匹配(大小写不敏感)。
+ */
+export function getOptionLines(
+ options: string,
+ answer: string
+): { text: string; isCorrect: boolean }[] {
+ const segments = answer
+ .split("#")
+ .map((s) => s.trim().toUpperCase())
+ .filter(Boolean);
+
+ return formatOptions(options)
+ .split("\n")
+ .filter((line) => line.trim())
+ .map((line) => {
+ const match = line.match(/^[A-Za-z]\.\s*(.*)/);
+ const content = match?.[1]?.trim().toUpperCase() ?? "";
+ const isCorrect = content !== "" && segments.includes(content);
+ return { text: line, isCorrect };
+ });
+}
diff --git a/app/utils/index.ts b/app/utils/index.ts
index 5a8d90b..edd6f06 100644
--- a/app/utils/index.ts
+++ b/app/utils/index.ts
@@ -1,2 +1,3 @@
export * from "./clipboard";
+export * from "./format";
export * from "./sortableTable";