|
|
@@ -10,9 +10,6 @@
|
|
|
clearable
|
|
|
@input="$emit('search', searchText)"
|
|
|
/>
|
|
|
- <el-button type="primary" size="small" icon="el-icon-plus" class="kbl-create-btn" @click="openCreateDialog">
|
|
|
- 新建知识库
|
|
|
- </el-button>
|
|
|
</div>
|
|
|
|
|
|
<!-- 列表 -->
|
|
|
@@ -23,7 +20,6 @@
|
|
|
class="kbl-item"
|
|
|
:class="{ 'kbl-item--active': activeId === kb.id }"
|
|
|
@click="$emit('select', kb.id)"
|
|
|
- @contextmenu.prevent="openContextMenu($event, kb)"
|
|
|
>
|
|
|
<div class="kbl-item-top">
|
|
|
<span class="kbl-item-icon"><i class="el-icon-folder-opened"></i></span>
|
|
|
@@ -48,82 +44,10 @@
|
|
|
|
|
|
<div v-if="list.length === 0" class="kbl-empty">
|
|
|
<p>暂无知识库</p>
|
|
|
- <p class="kbl-empty-tip">点击上方按钮创建</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 右键菜单 -->
|
|
|
- <div
|
|
|
- v-show="contextMenu.visible"
|
|
|
- class="kbl-context-menu"
|
|
|
- :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
|
|
|
- >
|
|
|
- <div class="kbl-menu-item" @click="openRenameDialog"><i class="el-icon-edit"></i> 重命名</div>
|
|
|
- <div class="kbl-menu-item" @click="openTagDialog"><i class="el-icon-price-tag"></i> 设置标签</div>
|
|
|
- <div class="kbl-menu-item kbl-menu-item--danger" @click="confirmDelete"><i class="el-icon-delete"></i> 删除</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 新建/重命名弹窗 -->
|
|
|
- <el-dialog
|
|
|
- :title="dialogTitle"
|
|
|
- :visible.sync="dialogVisible"
|
|
|
- width="460px"
|
|
|
- :close-on-click-modal="false"
|
|
|
- append-to-body
|
|
|
- >
|
|
|
- <el-form ref="kbForm" :model="formData" :rules="formRules" label-width="60px" size="small">
|
|
|
- <el-form-item label="名称" prop="name">
|
|
|
- <el-input v-model="formData.name" placeholder="请输入知识库名称" maxlength="30" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="描述" prop="description">
|
|
|
- <el-input
|
|
|
- v-model="formData.description"
|
|
|
- type="textarea"
|
|
|
- :rows="3"
|
|
|
- placeholder="请输入描述(选填)"
|
|
|
- maxlength="200"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- <span slot="footer">
|
|
|
- <el-button size="small" @click="dialogVisible = false">取 消</el-button>
|
|
|
- <el-button size="small" type="primary" @click="submitForm">确 定</el-button>
|
|
|
- </span>
|
|
|
- </el-dialog>
|
|
|
|
|
|
- <!-- 设置标签弹窗 -->
|
|
|
- <el-dialog
|
|
|
- title="设置标签"
|
|
|
- :visible.sync="tagDialogVisible"
|
|
|
- width="500px"
|
|
|
- :close-on-click-modal="false"
|
|
|
- append-to-body
|
|
|
- >
|
|
|
- <div class="kbl-tag-editor">
|
|
|
- <el-tag
|
|
|
- v-for="tag in editTags"
|
|
|
- :key="tag"
|
|
|
- closable
|
|
|
- :disable-transitions="false"
|
|
|
- size="small"
|
|
|
- @close="removeTag(tag)"
|
|
|
- >{{ tag }}</el-tag>
|
|
|
- <el-input
|
|
|
- v-if="tagInputVisible"
|
|
|
- ref="tagInput"
|
|
|
- v-model="tagInputValue"
|
|
|
- size="mini"
|
|
|
- class="kbl-tag-input"
|
|
|
- @keyup.enter.native="addTag"
|
|
|
- @blur="addTag"
|
|
|
- />
|
|
|
- <el-button v-else size="mini" @click="showTagInput">+ 添加标签</el-button>
|
|
|
- </div>
|
|
|
- <span slot="footer">
|
|
|
- <el-button size="small" @click="tagDialogVisible = false">取 消</el-button>
|
|
|
- <el-button size="small" type="primary" @click="submitTags">确 定</el-button>
|
|
|
- </span>
|
|
|
- </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -143,115 +67,11 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
searchText: '',
|
|
|
- contextMenu: { visible: false, x: 0, y: 0, kb: null },
|
|
|
- dialogVisible: false,
|
|
|
- dialogMode: 'create',
|
|
|
- formData: { name: '', description: '' },
|
|
|
- formRules: {
|
|
|
- name: [{ required: true, message: '请输入知识库名称', trigger: 'blur' }]
|
|
|
- },
|
|
|
- tagDialogVisible: false,
|
|
|
- editTags: [],
|
|
|
- tagInputVisible: false,
|
|
|
- tagInputValue: '',
|
|
|
- tagEditKB: null,
|
|
|
tagColorMap: {}
|
|
|
}
|
|
|
},
|
|
|
- computed: {
|
|
|
- dialogTitle() {
|
|
|
- return this.dialogMode === 'create' ? '新建知识库' : '重命名知识库'
|
|
|
- }
|
|
|
- },
|
|
|
- methods: {
|
|
|
- openCreateDialog() {
|
|
|
- this.dialogMode = 'create'
|
|
|
- this.formData = { name: '', description: '' }
|
|
|
- this.dialogVisible = true
|
|
|
- this.$nextTick(() => { this.$refs.kbForm && this.$refs.kbForm.clearValidate() })
|
|
|
- },
|
|
|
-
|
|
|
- openRenameDialog() {
|
|
|
- const kb = this.contextMenu.kb
|
|
|
- this.dialogMode = 'rename'
|
|
|
- this.formData = { name: kb.name, description: kb.description || '' }
|
|
|
- this.dialogVisible = true
|
|
|
- this.hideContextMenu()
|
|
|
- this.$nextTick(() => { this.$refs.kbForm && this.$refs.kbForm.clearValidate() })
|
|
|
- },
|
|
|
-
|
|
|
- submitForm() {
|
|
|
- this.$refs.kbForm.validate(valid => {
|
|
|
- if (!valid) return
|
|
|
- if (this.dialogMode === 'create') {
|
|
|
- this.$emit('create', { ...this.formData })
|
|
|
- } else {
|
|
|
- const kb = this.contextMenu.kb
|
|
|
- this.$emit('rename', { id: kb.id, name: this.formData.name, description: this.formData.description })
|
|
|
- }
|
|
|
- this.dialogVisible = false
|
|
|
- })
|
|
|
- },
|
|
|
-
|
|
|
- confirmDelete() {
|
|
|
- const kb = this.contextMenu.kb
|
|
|
- this.hideContextMenu()
|
|
|
- this.$confirm(`确定删除知识库「${kb.name}」吗?知识库下的所有文档也将被删除。`, '删除确认', {
|
|
|
- confirmButtonText: '确定删除',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
- }).then(() => {
|
|
|
- this.$emit('delete', kb.id)
|
|
|
- }).catch(() => {})
|
|
|
- },
|
|
|
-
|
|
|
- // 标签
|
|
|
- openTagDialog() {
|
|
|
- const kb = this.contextMenu.kb
|
|
|
- this.tagEditKB = kb
|
|
|
- this.editTags = [...(kb.tags || [])]
|
|
|
- this.tagDialogVisible = true
|
|
|
- this.hideContextMenu()
|
|
|
- },
|
|
|
-
|
|
|
- showTagInput() {
|
|
|
- this.tagInputVisible = true
|
|
|
- this.$nextTick(() => {
|
|
|
- this.$refs.tagInput && this.$refs.tagInput.$refs.input.focus()
|
|
|
- })
|
|
|
- },
|
|
|
-
|
|
|
- addTag() {
|
|
|
- const val = this.tagInputValue.trim()
|
|
|
- if (val && !this.editTags.includes(val)) {
|
|
|
- this.editTags.push(val)
|
|
|
- }
|
|
|
- this.tagInputVisible = false
|
|
|
- this.tagInputValue = ''
|
|
|
- },
|
|
|
-
|
|
|
- removeTag(tag) {
|
|
|
- const idx = this.editTags.indexOf(tag)
|
|
|
- if (idx > -1) this.editTags.splice(idx, 1)
|
|
|
- },
|
|
|
-
|
|
|
- submitTags() {
|
|
|
- if (this.tagEditKB) {
|
|
|
- this.$emit('set-tags', { id: this.tagEditKB.id, tags: this.editTags })
|
|
|
- }
|
|
|
- this.tagDialogVisible = false
|
|
|
- },
|
|
|
-
|
|
|
- // 右键菜单
|
|
|
- openContextMenu(e, kb) {
|
|
|
- this.contextMenu = { visible: true, x: e.clientX, y: e.clientY, kb }
|
|
|
- document.addEventListener('click', this.hideContextMenu, { once: true })
|
|
|
- },
|
|
|
-
|
|
|
- hideContextMenu() {
|
|
|
- this.contextMenu.visible = false
|
|
|
- },
|
|
|
|
|
|
+ methods: {
|
|
|
getTagColor(tag) {
|
|
|
if (!this.tagColorMap[tag]) {
|
|
|
const i = Object.keys(this.tagColorMap).length % TAG_COLORS.length
|
|
|
@@ -275,10 +95,6 @@ export default {
|
|
|
border-bottom: 1px solid #e4e7ed;
|
|
|
}
|
|
|
|
|
|
-.kbl-create-btn {
|
|
|
- width: 100%;
|
|
|
- margin-top: 8px;
|
|
|
-}
|
|
|
|
|
|
.kbl-list {
|
|
|
flex: 1;
|
|
|
@@ -367,49 +183,5 @@ export default {
|
|
|
margin-top: 4px;
|
|
|
}
|
|
|
|
|
|
-/* 右键菜单 */
|
|
|
-.kbl-context-menu {
|
|
|
- position: fixed;
|
|
|
- z-index: 3000;
|
|
|
- background: #fff;
|
|
|
- border: 1px solid #e4e7ed;
|
|
|
- border-radius: 4px;
|
|
|
- box-shadow: 0 2px 12px rgba(0,0,0,0.12);
|
|
|
- padding: 4px 0;
|
|
|
- min-width: 140px;
|
|
|
-}
|
|
|
-
|
|
|
-.kbl-menu-item {
|
|
|
- padding: 8px 16px;
|
|
|
- font-size: 13px;
|
|
|
- cursor: pointer;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 6px;
|
|
|
-}
|
|
|
-
|
|
|
-.kbl-menu-item:hover {
|
|
|
- background: #f5f7fa;
|
|
|
-}
|
|
|
|
|
|
-.kbl-menu-item--danger {
|
|
|
- color: #F56C6C;
|
|
|
-}
|
|
|
-
|
|
|
-.kbl-menu-item--danger:hover {
|
|
|
- background: #fef0f0;
|
|
|
-}
|
|
|
-
|
|
|
-/* 标签编辑 */
|
|
|
-.kbl-tag-editor {
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: 8px;
|
|
|
- align-items: center;
|
|
|
- min-height: 32px;
|
|
|
-}
|
|
|
-
|
|
|
-.kbl-tag-input {
|
|
|
- width: 100px;
|
|
|
-}
|
|
|
</style>
|