|
@@ -162,11 +162,19 @@
|
|
|
:key="`${group.id}-${index}`"
|
|
:key="`${group.id}-${index}`"
|
|
|
class="checklist-row"
|
|
class="checklist-row"
|
|
|
>
|
|
>
|
|
|
- <div class="checklist-item">
|
|
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ :class="['checklist-item', { collapsed: isCaseCollapsed(group.id, index) }]"
|
|
|
|
|
+ @click="toggleCase(group.id, index)"
|
|
|
|
|
+ >
|
|
|
<span class="item-index">{{ index + 1 }}</span>
|
|
<span class="item-index">{{ index + 1 }}</span>
|
|
|
<span class="item-text">{{ item.text }}</span>
|
|
<span class="item-text">{{ item.text }}</span>
|
|
|
- </div>
|
|
|
|
|
- <div class="case-examples">
|
|
|
|
|
|
|
+ <span class="item-caret">▼</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <div v-show="!isCaseCollapsed(group.id, index)" class="case-examples">
|
|
|
|
|
+ <button class="case-view-btn" type="button" @click="openCaseViewer">
|
|
|
|
|
+ 查看大图
|
|
|
|
|
+ </button>
|
|
|
<div class="case-card positive">
|
|
<div class="case-card positive">
|
|
|
<div class="case-title">正确示例</div>
|
|
<div class="case-title">正确示例</div>
|
|
|
<img src="/case-positive.png" alt="正确示例" />
|
|
<img src="/case-positive.png" alt="正确示例" />
|
|
@@ -183,6 +191,25 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+ <div v-if="showCaseViewer" class="case-viewer" @click.self="closeCaseViewer">
|
|
|
|
|
+ <div class="case-viewer-panel">
|
|
|
|
|
+ <div class="case-viewer-header">
|
|
|
|
|
+ <span>正反案例对比</span>
|
|
|
|
|
+ <button type="button" class="case-viewer-close" @click="closeCaseViewer">×</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="case-viewer-body">
|
|
|
|
|
+ <div class="case-viewer-card positive">
|
|
|
|
|
+ <div class="case-viewer-title">正确示例</div>
|
|
|
|
|
+ <img src="/case-positive.png" alt="正确示例" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="case-viewer-card negative">
|
|
|
|
|
+ <div class="case-viewer-title">错误示例</div>
|
|
|
|
|
+ <img src="/case-negative.png" alt="错误示例" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
@@ -390,9 +417,13 @@ const detectionGroups = computed(() => [
|
|
|
])
|
|
])
|
|
|
|
|
|
|
|
const expandedGroupId = ref(null)
|
|
const expandedGroupId = ref(null)
|
|
|
|
|
+const collapsedCaseKeys = ref([])
|
|
|
|
|
+const showCaseViewer = ref(false)
|
|
|
|
|
+
|
|
|
const selectTask = (task) => {
|
|
const selectTask = (task) => {
|
|
|
currentTaskId.value = task.id
|
|
currentTaskId.value = task.id
|
|
|
expandedGroupId.value = null
|
|
expandedGroupId.value = null
|
|
|
|
|
+ collapsedCaseKeys.value = []
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const selectTag = (tag) => {
|
|
const selectTag = (tag) => {
|
|
@@ -407,6 +438,30 @@ const toggleCheck = (index) => {
|
|
|
|
|
|
|
|
const toggleGroup = (groupId) => {
|
|
const toggleGroup = (groupId) => {
|
|
|
expandedGroupId.value = expandedGroupId.value === groupId ? null : groupId
|
|
expandedGroupId.value = expandedGroupId.value === groupId ? null : groupId
|
|
|
|
|
+ collapsedCaseKeys.value = []
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const getCaseKey = (groupId, itemIndex) => `${groupId}-${itemIndex}`
|
|
|
|
|
+
|
|
|
|
|
+const isCaseCollapsed = (groupId, itemIndex) => {
|
|
|
|
|
+ return collapsedCaseKeys.value.includes(getCaseKey(groupId, itemIndex))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const toggleCase = (groupId, itemIndex) => {
|
|
|
|
|
+ const key = getCaseKey(groupId, itemIndex)
|
|
|
|
|
+ if (collapsedCaseKeys.value.includes(key)) {
|
|
|
|
|
+ collapsedCaseKeys.value = collapsedCaseKeys.value.filter(item => item !== key)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ collapsedCaseKeys.value = [...collapsedCaseKeys.value, key]
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const openCaseViewer = () => {
|
|
|
|
|
+ showCaseViewer.value = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const closeCaseViewer = () => {
|
|
|
|
|
+ showCaseViewer.value = false
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
@@ -936,14 +991,30 @@ const toggleGroup = (groupId) => {
|
|
|
|
|
|
|
|
.checklist-item {
|
|
.checklist-item {
|
|
|
display: grid;
|
|
display: grid;
|
|
|
- grid-template-columns: 22px minmax(0, 1fr);
|
|
|
|
|
|
|
+ grid-template-columns: 22px minmax(0, 1fr) 14px;
|
|
|
gap: 10px;
|
|
gap: 10px;
|
|
|
align-items: flex-start;
|
|
align-items: flex-start;
|
|
|
width: calc(100% - 28px);
|
|
width: calc(100% - 28px);
|
|
|
margin: 0 14px;
|
|
margin: 0 14px;
|
|
|
padding: 9px 14px;
|
|
padding: 9px 14px;
|
|
|
|
|
+ border: 0;
|
|
|
border-radius: 7px;
|
|
border-radius: 7px;
|
|
|
background: #fff;
|
|
background: #fff;
|
|
|
|
|
+ text-align: left;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+
|
|
|
|
|
+ &:focus,
|
|
|
|
|
+ &:focus-visible,
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ outline: none;
|
|
|
|
|
+ box-shadow: none;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.collapsed {
|
|
|
|
|
+ .item-caret {
|
|
|
|
|
+ transform: rotate(-90deg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
.item-index {
|
|
.item-index {
|
|
|
width: 22px;
|
|
width: 22px;
|
|
@@ -965,9 +1036,17 @@ const toggleGroup = (groupId) => {
|
|
|
color: #4b5568;
|
|
color: #4b5568;
|
|
|
line-height: 1.55;
|
|
line-height: 1.55;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ .item-caret {
|
|
|
|
|
+ color: #a6afbd;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 22px;
|
|
|
|
|
+ transition: transform 0.2s ease;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.case-examples {
|
|
.case-examples {
|
|
|
|
|
+ position: relative;
|
|
|
display: grid;
|
|
display: grid;
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
gap: 12px;
|
|
gap: 12px;
|
|
@@ -978,6 +1057,27 @@ const toggleGroup = (groupId) => {
|
|
|
border: 1px solid #e7ecf3;
|
|
border: 1px solid #e7ecf3;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ .case-view-btn {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 10px;
|
|
|
|
|
+ right: 10px;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ padding: 4px 10px;
|
|
|
|
|
+ border: 1px solid #3f7cff;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.92);
|
|
|
|
|
+ color: #3f7cff;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+
|
|
|
|
|
+ &:focus,
|
|
|
|
|
+ &:focus-visible,
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ outline: none;
|
|
|
|
|
+ box-shadow: none;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
.case-card {
|
|
.case-card {
|
|
|
min-width: 0;
|
|
min-width: 0;
|
|
|
|
|
|
|
@@ -1013,4 +1113,109 @@ const toggleGroup = (groupId) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+.case-viewer {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ inset: 0;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ padding: 28px;
|
|
|
|
|
+ background: rgba(12, 20, 38, 0.72);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.case-viewer-panel {
|
|
|
|
|
+ width: min(1500px, 96vw);
|
|
|
|
|
+ height: min(860px, 92vh);
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.28);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.case-viewer-header {
|
|
|
|
|
+ height: 54px;
|
|
|
|
|
+ padding: 0 18px 0 22px;
|
|
|
|
|
+ border-bottom: 1px solid #edf0f5;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: #1f2937;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.case-viewer-close {
|
|
|
|
|
+ width: 34px;
|
|
|
|
|
+ height: 34px;
|
|
|
|
|
+ border: 0;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: #f3f6fb;
|
|
|
|
|
+ color: #4b5568;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ line-height: 1;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ background: #e7ecf3;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &:focus,
|
|
|
|
|
+ &:focus-visible,
|
|
|
|
|
+ &:active {
|
|
|
|
|
+ outline: none;
|
|
|
|
|
+ box-shadow: none;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.case-viewer-body {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-height: 0;
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
+ gap: 18px;
|
|
|
|
|
+ padding: 18px;
|
|
|
|
|
+ background: #f6f8fb;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.case-viewer-card {
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 10px;
|
|
|
|
|
+
|
|
|
|
|
+ .case-viewer-title {
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-height: 0;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ object-fit: contain;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.positive .case-viewer-title {
|
|
|
|
|
+ color: #16a34a;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.negative .case-viewer-title {
|
|
|
|
|
+ color: #dc2626;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@media (max-width: 900px) {
|
|
|
|
|
+ .case-viewer-body {
|
|
|
|
|
+ grid-template-columns: 1fr;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|