|
@@ -1,9 +1,36 @@
|
|
|
<template>
|
|
|
<el-tabs v-model="activeTab" class="chapter-tabs">
|
|
|
<el-tab-pane label="章节列表" name="chapters">
|
|
|
- <div class="chapter-list">
|
|
|
- 章节列表
|
|
|
+ <div class="tree-container" @contextmenu="handleContextMenu">
|
|
|
+ <el-tree
|
|
|
+ class="chapter-list"
|
|
|
+ :data="chapterData"
|
|
|
+ node-key="id"
|
|
|
+ :props="{ label: 'label', children: 'children' }"
|
|
|
+ default-expand-all
|
|
|
+ ></el-tree>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 右键菜单 -->
|
|
|
+ <div
|
|
|
+ v-show="contextMenuVisible"
|
|
|
+ class="custom-context-menu"
|
|
|
+ :style="{ top: contextMenuPosition.y + 'px', left: contextMenuPosition.x + 'px' }"
|
|
|
+ @click.stop
|
|
|
+ >
|
|
|
+ <ul>
|
|
|
+ <li @click="openAddDialog">添加章节</li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 添加章节对话框 -->
|
|
|
+ <el-dialog title="添加章节" v-model="showAddDialog" width="300px">
|
|
|
+ <el-input v-model="newChapterName" placeholder="输入章节名称"></el-input>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="showAddDialog = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="addChapter">确定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</el-tab-pane>
|
|
|
<el-tab-pane label="书籍信息" name="info">
|
|
|
<div class="book-info">
|
|
@@ -14,16 +41,110 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref } from 'vue';
|
|
|
-import { ElTabs, ElTabPane } from 'element-plus';
|
|
|
+import { ref, onUnmounted, watch } from 'vue';
|
|
|
+import { ElTabs, ElTabPane, ElTree, ElInput, ElButton, ElDialog } from 'element-plus';
|
|
|
const activeTab = ref('chapters');
|
|
|
+const contextMenuVisible = ref(false);
|
|
|
+const contextMenuPosition = ref({ x: 0, y: 0 });
|
|
|
+const currentNode = ref(null);
|
|
|
+const chapterData = ref([{
|
|
|
+ id: 1,
|
|
|
+ label: '第一章',
|
|
|
+ children: [{
|
|
|
+ id: 2,
|
|
|
+ label: '1.1 节'
|
|
|
+ }]
|
|
|
+}]);
|
|
|
+const showAddDialog = ref(false);
|
|
|
+const newChapterName = ref('');
|
|
|
+
|
|
|
+// 处理右键菜单事件
|
|
|
+const handleContextMenu = (event) => {
|
|
|
+ event.preventDefault();
|
|
|
+ console.log('右键菜单事件触发');
|
|
|
+ console.log('事件目标:', event.target);
|
|
|
+ console.log('当前鼠标位置:', { x: event.clientX, y: event.clientY });
|
|
|
+ contextMenuPosition.value = { x: event.clientX, y: event.clientY };
|
|
|
+ contextMenuVisible.value = true;
|
|
|
+ console.log('设置contextMenuVisible为true');
|
|
|
+ // 阻止事件冒泡
|
|
|
+ event.stopPropagation();
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+// 监控contextMenuVisible变化
|
|
|
+watch(contextMenuVisible, (newValue) => {
|
|
|
+ console.log('contextMenuVisible变化:', newValue);
|
|
|
+});
|
|
|
+
|
|
|
+// 打开添加章节对话框
|
|
|
+const openAddDialog = () => {
|
|
|
+ contextMenuVisible.value = false;
|
|
|
+ showAddDialog.value = true;
|
|
|
+ newChapterName.value = '';
|
|
|
+};
|
|
|
+
|
|
|
+// 添加章节
|
|
|
+const addChapter = () => {
|
|
|
+ if (!newChapterName.value.trim()) {
|
|
|
+ console.log('章节名称不能为空');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const newChapter = {
|
|
|
+ id: Date.now(),
|
|
|
+ label: newChapterName.value.trim(),
|
|
|
+ children: []
|
|
|
+ };
|
|
|
+
|
|
|
+ if (currentNode.value) {
|
|
|
+ // 如果有选中节点,添加为子节点
|
|
|
+ if (!currentNode.value.children) {
|
|
|
+ currentNode.value.children = [];
|
|
|
+ }
|
|
|
+ currentNode.value.children.push(newChapter);
|
|
|
+ } else {
|
|
|
+ // 如果没有选中节点,添加到根节点
|
|
|
+ chapterData.value.push(newChapter);
|
|
|
+ }
|
|
|
+
|
|
|
+ showAddDialog.value = false;
|
|
|
+ console.log('章节添加成功');
|
|
|
+};
|
|
|
+
|
|
|
+// 点击其他区域关闭菜单
|
|
|
+const handleClickOutside = (e) => {
|
|
|
+ const contextMenu = document.querySelector('.custom-context-menu');
|
|
|
+ if (contextMenu && !contextMenu.contains(e.target)) {
|
|
|
+ contextMenuVisible.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+document.addEventListener('click', handleClickOutside);
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ document.removeEventListener('click', handleClickOutside);
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
.chapter-tabs { height: 100%; }
|
|
|
-.chapter-list { padding: 10px; }
|
|
|
-.chapter-item { padding: 8px 12px; margin-bottom: 4px; cursor: pointer; border-radius: 4px; transition: background-color 0.2s; }
|
|
|
-.chapter-item:hover { background-color: #f5f5f5; }
|
|
|
+.tree-container {
|
|
|
+ height: 80vh;
|
|
|
+ overflow: auto;
|
|
|
+}
|
|
|
+.chapter-list { width: 100%; }
|
|
|
+.custom-context-menu {
|
|
|
+ position: fixed;
|
|
|
+ z-index: 9999;
|
|
|
+ background-color: #fff;
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ border-radius: 4px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
+ min-width: 100px;
|
|
|
+}
|
|
|
+ul { list-style: none; padding: 0; margin: 0; }
|
|
|
+li { padding: 6px 12px; cursor: pointer; }
|
|
|
+li:hover { background-color: #f5f5f5; }
|
|
|
.book-info { padding: 15px; }
|
|
|
-.info-item { margin-bottom: 10px; }
|
|
|
</style>
|