|
@@ -2,10 +2,55 @@
|
|
|
<el-tabs v-model="activeTab" class="chapter-tabs">
|
|
|
<el-tab-pane label="章节列表" name="chapters">
|
|
|
<div class="tree-container">
|
|
|
- 这还是个树
|
|
|
+ <el-button type="primary" @click="openAddVolumeDialog" style="margin-bottom: 10px;" circle :title="'添加卷'">
|
|
|
+ <el-icon>
|
|
|
+ <Plus />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-tree class="chapter-list" :data="treeData" node-key="id" :props="{ label: 'label', children: 'children' }"
|
|
|
+ default-expand-all>
|
|
|
+ <template #default="{ data }">
|
|
|
+ <span class="custom-tree-node">
|
|
|
+ <span>{{ data.label }}</span>
|
|
|
+ <span class="node-actions">
|
|
|
+ <el-button v-if="data.type === 'volume'" size="small" type="text"
|
|
|
+ @click.stop="openAddChapterDialog(data)" circle :title="'添加章'">
|
|
|
+ <el-icon>
|
|
|
+ <Plus />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="text" @click.stop="openEditDialog(data)" circle :title="'编辑'">
|
|
|
+ <el-icon>
|
|
|
+ <Edit />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="text" @click.stop="deleteNode(data)" class="delete-btn" circle
|
|
|
+ :title="'删除'">
|
|
|
+ <el-icon>
|
|
|
+ <Delete />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-tree>
|
|
|
</div>
|
|
|
+ <el-dialog v-model="showAddDialog" :title="addDialogTitle" width="300px">
|
|
|
+ <el-input v-model="newNodeName" :placeholder="addDialogPlaceholder"></el-input>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="showAddDialog = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmAddNode">确定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog v-model="showEditDialog" title="编辑名称" width="300px">
|
|
|
+ <el-input v-model="editNodeName" placeholder="请输入名称"></el-input>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="showEditDialog = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmEditNode">确定</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</el-tab-pane>
|
|
|
-
|
|
|
+ <!-- 维护书籍信息 -->
|
|
|
<el-tab-pane label="书籍信息" name="info">
|
|
|
<div class="book-info">
|
|
|
书籍信息
|
|
@@ -16,10 +61,104 @@
|
|
|
|
|
|
<script setup>
|
|
|
import { ref } from 'vue';
|
|
|
-import { ElTabs, ElTabPane } from 'element-plus';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { Plus, Edit, Delete } from '@element-plus/icons-vue';
|
|
|
|
|
|
const activeTab = ref('chapters');
|
|
|
|
|
|
+// 卷-章树数据
|
|
|
+const treeData = ref([
|
|
|
+
|
|
|
+]);
|
|
|
+
|
|
|
+// 添加节点弹窗
|
|
|
+const showAddDialog = ref(false);
|
|
|
+const addDialogTitle = ref('');
|
|
|
+const addDialogPlaceholder = ref('');
|
|
|
+const newNodeName = ref('');
|
|
|
+let addNodeType = '';
|
|
|
+let addParentNode = null;
|
|
|
+
|
|
|
+// 编辑节点弹窗
|
|
|
+const showEditDialog = ref(false);
|
|
|
+const editNodeName = ref('');
|
|
|
+let editNode = null;
|
|
|
+
|
|
|
+// 添加卷
|
|
|
+function openAddVolumeDialog() {
|
|
|
+ showAddDialog.value = true;
|
|
|
+ addDialogTitle.value = '添加卷';
|
|
|
+ addDialogPlaceholder.value = '请输入卷名';
|
|
|
+ newNodeName.value = '';
|
|
|
+ addNodeType = 'volume';
|
|
|
+ addParentNode = null;
|
|
|
+}
|
|
|
+// 添加章
|
|
|
+function openAddChapterDialog(parent) {
|
|
|
+ showAddDialog.value = true;
|
|
|
+ addDialogTitle.value = '添加章';
|
|
|
+ addDialogPlaceholder.value = '请输入章名';
|
|
|
+ newNodeName.value = '';
|
|
|
+ addNodeType = 'chapter';
|
|
|
+ addParentNode = parent;
|
|
|
+}
|
|
|
+// 确认添加
|
|
|
+function confirmAddNode() {
|
|
|
+ const name = newNodeName.value.trim();
|
|
|
+ if (!name) {
|
|
|
+ ElMessage.warning('名称不能为空');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (addNodeType === 'volume') {
|
|
|
+ treeData.value.push({
|
|
|
+ id: Date.now(),
|
|
|
+ label: name,
|
|
|
+ type: 'volume',
|
|
|
+ children: []
|
|
|
+ });
|
|
|
+ } else if (addNodeType === 'chapter' && addParentNode) {
|
|
|
+ addParentNode.children.push({
|
|
|
+ id: Date.now(),
|
|
|
+ label: name,
|
|
|
+ type: 'chapter',
|
|
|
+ children: []
|
|
|
+ });
|
|
|
+ }
|
|
|
+ showAddDialog.value = false;
|
|
|
+}
|
|
|
+// 编辑
|
|
|
+function openEditDialog(node) {
|
|
|
+ showEditDialog.value = true;
|
|
|
+ editNodeName.value = node.label;
|
|
|
+ editNode = node;
|
|
|
+}
|
|
|
+function confirmEditNode() {
|
|
|
+ const name = editNodeName.value.trim();
|
|
|
+ if (!name) {
|
|
|
+ ElMessage.warning('名称不能为空');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (editNode) {
|
|
|
+ editNode.label = name;
|
|
|
+ }
|
|
|
+ showEditDialog.value = false;
|
|
|
+}
|
|
|
+// 删除
|
|
|
+function deleteNode(node) {
|
|
|
+ function findAndRemove(nodes, targetId) {
|
|
|
+ for (let i = 0; i < nodes.length; i++) {
|
|
|
+ if (nodes[i].id === targetId) {
|
|
|
+ nodes.splice(i, 1);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (nodes[i].children) {
|
|
|
+ if (findAndRemove(nodes[i].children, targetId)) return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ findAndRemove(treeData.value, node.id);
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
@@ -27,10 +166,6 @@ const activeTab = ref('chapters');
|
|
|
height: 100%;
|
|
|
}
|
|
|
|
|
|
-.search-container {
|
|
|
- margin-bottom: 10px;
|
|
|
-}
|
|
|
-
|
|
|
.tree-container {
|
|
|
height: calc(80vh - 60px);
|
|
|
overflow: auto;
|
|
@@ -39,4 +174,19 @@ const activeTab = ref('chapters');
|
|
|
.chapter-list {
|
|
|
width: 100%;
|
|
|
}
|
|
|
+
|
|
|
+.custom-tree-node {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.node-actions {
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.delete-btn {
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
</style>
|