Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:新增添加帖子标签功能 #64

Merged
merged 3 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/assets/icons/iconfont.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 4414354 */
src: url('iconfont.woff2?t=1707987260666') format('woff2'),
url('iconfont.woff?t=1707987260666') format('woff'),
url('iconfont.ttf?t=1707987260666') format('truetype');
src: url('iconfont.woff2?t=1708153151921') format('woff2'),
url('iconfont.woff?t=1708153151921') format('woff'),
url('iconfont.ttf?t=1708153151921') format('truetype');
}

.iconfont {
Expand All @@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}

.icon-sousuo:before {
content: "\e624";
}

.icon-ffanhui-:before {
content: "\e6b1";
}
Expand Down
2 changes: 1 addition & 1 deletion src/assets/icons/iconfont.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/assets/icons/iconfont.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "1614453",
"name": "搜索",
"font_class": "sousuo",
"unicode": "e624",
"unicode_decimal": 58916
},
{
"icon_id": "5365351",
"name": "返回",
Expand Down
Binary file modified src/assets/icons/iconfont.ttf
Binary file not shown.
Binary file modified src/assets/icons/iconfont.woff
Binary file not shown.
Binary file modified src/assets/icons/iconfont.woff2
Binary file not shown.
9 changes: 9 additions & 0 deletions src/views/posts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,13 @@ export const getOtherPosts = async () => {
}
})
return postsList.value
}

export const getTagsList = async(key: string) =>{
const url = '/label/getLabels?key=' + key
const tagsList = ref<string[]>([])
await get(url).then((res: any) => {
tagsList.value = res.labels.map((label: any) => label.value)
})
return tagsList.value
}
172 changes: 157 additions & 15 deletions src/views/posts/write.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="main-box">
<div class="main-box" @click="handleClickTagOutside">
<div class="editor-box">
<header class="header">
<i class="iconfont icon-ffanhui- back"></i>
Expand Down Expand Up @@ -64,10 +64,43 @@
</label>
</div>
</div>
<div class="add-tag">
<div>添加帖子标签</div>
<input type="text">
<i class="iconfont icon-jia"></i>
<div class="add-tag-box">
<div
class="tag-contents"
:style="{left: tagContentsLeft + 'px'}"
v-show="isShowSearchTag"
>
<div class="search">
<i class="iconfont icon-sousuo"></i>
<input
v-model="searchContent"
type="text"
@keydown="getTagList"
>
</div>
<div class="cur-tag-box">
<div
class="cur-tag"
v-for="(tag, index) in tagsList"
:key="index"
@click="selectTag(tag)"
>{{ tag }}</div>
</div>
</div>
<div style="margin-right: 20px;">添加帖子标签</div>
<div
class="tag"
v-for="(tag, index) in nowTagsList"
:key="index"
>
<div>{{ tag }}</div>
<i class="iconfont icon-cuowu1" @click="deleteTag(index)"></i>
</div>
<i
class="iconfont icon-jia add-tag-button"
v-if="nowTagsCount < 5"
@click="addTags($event)"
></i>
</div>
<div class="operate">
<button @click="previewPost" :disabled="isOperate">预览</button>
Expand All @@ -81,17 +114,26 @@

<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { onBeforeUnmount, onUpdated, ref, shallowRef } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { errorMsg } from '@/utils/message'
import { debounce } from '@/utils/optimize'
import { cosUploadImage } from '@/utils/public-cos'
import { getTagsList } from './utils'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { onBeforeUnmount, onUpdated, ref, shallowRef } from 'vue'

const coverImage = ref('') // 封面图片
const valueHtml = ref('') // 文章内容
const postTitle = ref('') // 文章标题
const searchContent = ref('')
const editorRef = shallowRef()
const isOperate = ref(true)
const isShowOperate = ref(false)
const isUploadImage = ref(false)
const isShowSearchTag = ref(false)
const nowTagsCount = ref(0)
const tagContentsLeft = ref(0)
const tagsList = ref<string[]>([])
const nowTagsList = ref<string[]>([])
const editorConfig = { placeholder: '请输入内容...' }
const toolbarConfig = {
toolbarKeys: [
Expand Down Expand Up @@ -143,6 +185,41 @@ onUpdated(() => {
}
})

const getTagList = debounce(async() => {
if (!searchContent.value) {
return
}
tagsList.value = await getTagsList(searchContent.value).then()
}, 500)
const deleteTag = (index: number) => {
nowTagsCount.value --
nowTagsList.value.splice(index, 1)
}
const selectTag = (tag: string) => {
if (nowTagsList.value.includes(tag)) {
errorMsg('已经添加过该标签了');
return
}
nowTagsCount.value ++
nowTagsList.value.push(tag)
isShowSearchTag.value = false
}
const addTags = (event: Event) => {
const target = event.target as HTMLElement
const left = target.offsetLeft
tagContentsLeft.value = left
isShowSearchTag.value = true
}
const handleClickTagOutside = (event: Event) => {
if ((event.target as HTMLElement).closest('.tag-contents') || (event.target as HTMLElement).closest('.add-tag-button')) {
isShowSearchTag.value = true
}
else {
isShowSearchTag.value = false
searchContent.value = ''
}
}

const deleteImage = () => {
coverImage.value = ''
isUploadImage.value = false
Expand Down Expand Up @@ -336,22 +413,87 @@ const previewPost = () => {
}
}

.add-tag {
.add-tag-box {
position: relative;
height: 50px;
display: flex;
align-items: center;

input {
width: 150px;
height: 30px;
margin-left: 30px;
padding-left: 10px;
.tag-contents {
position: absolute;
width: 250px;
bottom: 50px;
padding: 10px;
border-radius: 5px;
background-color: #fff;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);

.search {
width: 100%;
height: 40px;
border: 1px solid #ccc;
border-radius: 60px;
padding-left: 10px;
margin-top: 10px;
margin-bottom: 8px;
display: flex;
align-items: center;

i {
font-size: 20px;
font-weight: 700;
color: #2e4482;
margin-right: 10px;
}

input {
width: 80%;
height: 30px;
border: none;
outline: none;
}
}

.cur-tag-box {
width: 100%;
max-height: 250px;
overflow-y: auto;

.cur-tag {
width: 100%;
height: 40px;
padding-left: 10px;
line-height: 40px;
color: #000;
cursor: pointer;
}
.cur-tag:hover {
background-color: #f5f5f5;
}
}
}

.tag {
height: 35px;
padding: 8px 15px;
margin-right: 10px;
display: flex;
align-items: center;
border: 1px solid #ccc;
border-radius: 20px;
color: #3b5393;

i {
font-size: 20px;
color: #ccc;
cursor: pointer;
}
}


i {
font-size: 30px;
margin-left: 20px;
margin-left: 5px;
font-size: 25px;
color: #ccc;
cursor: pointer;
}
Expand Down
Loading