|
|
@@ -78,17 +78,47 @@
|
|
|
v-for="(item, index) in contentList"
|
|
|
:key="index"
|
|
|
class="content-item"
|
|
|
- @click="insertContent(item)"
|
|
|
>
|
|
|
- <svg class="content-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
- <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
|
|
|
- <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
|
|
|
- </svg>
|
|
|
- <span class="content-label">{{ item.title }}</span>
|
|
|
- <span class="type-tag" :class="getTypeClass(item.tool)">{{ getTypeLabel(item.tool) }}</span>
|
|
|
+ <div class="content-main" @click="insertContent(item)">
|
|
|
+ <svg class="content-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
|
|
|
+ <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
|
|
|
+ </svg>
|
|
|
+ <span class="content-label">{{ item.title }}</span>
|
|
|
+ <span class="type-tag" :class="getTypeClass(item.tool)">{{ getTypeLabel(item.tool) }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="content-actions">
|
|
|
+ <template v-if="item.tool === 74 || item.tool === 75">
|
|
|
+ <div class="action-btn" @click.stop="previewVideo(item)" title="预览">
|
|
|
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <polygon points="5 3 19 12 5 21 5 3"/>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-if="item.tool !== 76">
|
|
|
+ <div class="action-btn" @click.stop="editContent(item)" title="编辑">
|
|
|
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
|
|
|
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ <div class="action-btn" @click.stop="copyContent(item)" title="复制">
|
|
|
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
|
|
|
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="action-btn delete" @click.stop="deleteContent(item)" title="删除">
|
|
|
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <polyline points="3 6 5 6 21 6"/>
|
|
|
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -100,6 +130,7 @@ interface ContentItem {
|
|
|
tool?: number
|
|
|
title?: string
|
|
|
url?: string
|
|
|
+ id?: string
|
|
|
}
|
|
|
|
|
|
const props = withDefaults(defineProps<{
|
|
|
@@ -135,8 +166,6 @@ const toggleSubmenu = (menu: string) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
const handleToolClick = (tool: string) => {
|
|
|
interface ParentWindowWithToolList extends Window {
|
|
|
addTool?: (id: number) => void;
|
|
|
@@ -181,13 +210,43 @@ const loadContentList = () => {
|
|
|
|
|
|
(window as any).loadContentList = loadContentList
|
|
|
|
|
|
-
|
|
|
-
|
|
|
const insertContent = (item: ContentItem) => {
|
|
|
if (!item.tool || !item.url) return
|
|
|
createFrameElement(item.url, item.tool)
|
|
|
}
|
|
|
|
|
|
+const previewVideo = (item: ContentItem) => {
|
|
|
+ interface ParentWindowWithToolList extends Window {
|
|
|
+ previewVideo?: (item: ContentItem) => void;
|
|
|
+ }
|
|
|
+ const parentWindow = window.parent as ParentWindowWithToolList
|
|
|
+ parentWindow?.previewVideo?.(item)
|
|
|
+}
|
|
|
+
|
|
|
+const editContent = (item: ContentItem) => {
|
|
|
+ interface ParentWindowWithToolList extends Window {
|
|
|
+ toolBtn?: (action: number, id: string) => void;
|
|
|
+ }
|
|
|
+ const parentWindow = window.parent as ParentWindowWithToolList
|
|
|
+ parentWindow?.toolBtn?.(0, item.id || '')
|
|
|
+}
|
|
|
+
|
|
|
+const copyContent = (item: ContentItem) => {
|
|
|
+ interface ParentWindowWithToolList extends Window {
|
|
|
+ toolBtn?: (action: number, id: string) => void;
|
|
|
+ }
|
|
|
+ const parentWindow = window.parent as ParentWindowWithToolList
|
|
|
+ parentWindow?.toolBtn?.(1, item.id || '')
|
|
|
+}
|
|
|
+
|
|
|
+const deleteContent = (item: ContentItem) => {
|
|
|
+ interface ParentWindowWithToolList extends Window {
|
|
|
+ toolBtn?: (action: number, id: string) => void;
|
|
|
+ }
|
|
|
+ const parentWindow = window.parent as ParentWindowWithToolList
|
|
|
+ parentWindow?.toolBtn?.(2, item.id || '')
|
|
|
+}
|
|
|
+
|
|
|
const getTypeLabel = (type?: number) => {
|
|
|
const typeMap: Record<number, string> = {
|
|
|
45: '选择题',
|
|
|
@@ -372,8 +431,8 @@ const getTypeClass = (type?: number) => {
|
|
|
z-index: 100;
|
|
|
|
|
|
&.visible {
|
|
|
- width: 300px;
|
|
|
- min-width: 300px;
|
|
|
+ width: 380px;
|
|
|
+ min-width: 380px;
|
|
|
padding: 8px 0;
|
|
|
}
|
|
|
}
|
|
|
@@ -421,21 +480,31 @@ const getTypeClass = (type?: number) => {
|
|
|
.content-item {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- gap: 8px;
|
|
|
+ justify-content: space-between;
|
|
|
padding: 8px 12px;
|
|
|
- cursor: pointer;
|
|
|
- transition: all 0.2s ease;
|
|
|
border-radius: 8px;
|
|
|
margin: 2px 8px;
|
|
|
position: relative;
|
|
|
+ transition: all 0.2s ease;
|
|
|
|
|
|
&:hover {
|
|
|
- background-color: #f3f4f6;
|
|
|
- color: #285cf5;
|
|
|
+ background-color: #f8f9fa;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- &:active {
|
|
|
- background-color: #e5e7eb;
|
|
|
+.content-main {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 4px;
|
|
|
+ border-radius: 6px;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: #f3f4f6;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -446,7 +515,7 @@ const getTypeClass = (type?: number) => {
|
|
|
color: #9ca3af;
|
|
|
}
|
|
|
|
|
|
-.content-item:hover .content-icon {
|
|
|
+.content-main:hover .content-icon {
|
|
|
color: #285cf5;
|
|
|
}
|
|
|
|
|
|
@@ -459,10 +528,45 @@ const getTypeClass = (type?: number) => {
|
|
|
text-overflow: ellipsis;
|
|
|
}
|
|
|
|
|
|
-.content-item:hover .content-label {
|
|
|
+.content-main:hover .content-label {
|
|
|
color: #285cf5;
|
|
|
}
|
|
|
|
|
|
+.content-actions {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn {
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+ color: #9ca3af;
|
|
|
+
|
|
|
+ svg {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: #f3f4f6;
|
|
|
+ color: #285cf5;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.delete {
|
|
|
+ &:hover {
|
|
|
+ background-color: #fee2e2;
|
|
|
+ color: #ef4444;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.type-tag {
|
|
|
padding: 2px 6px;
|
|
|
border-radius: 4px;
|