Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
corporateCulture-qd
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
王立鹏
corporateCulture-qd
Commits
7bdc7b3d
Commit
7bdc7b3d
authored
Dec 14, 2025
by
lijiabin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【需求 17679】 perf: 优化实践相关的内容
parent
61a43a4a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
68 additions
and
131 deletions
+68
-131
index.vue
src/components/common/PublishBox/index.vue
+29
-63
practiceForm.tsx
src/layoutCulture/components/practiceForm.tsx
+1
-2
practiceList.vue
src/views/homePage/yaTab/components/practiceList.vue
+38
-66
No files found.
src/components/common/PublishBox/index.vue
View file @
7bdc7b3d
...
@@ -5,32 +5,21 @@
...
@@ -5,32 +5,21 @@
<div
class=
"flex gap-3 mb-2 items-start"
>
<div
class=
"flex gap-3 mb-2 items-start"
>
<!-- 用户头像 -->
<!-- 用户头像 -->
<el-avatar
:size=
"48"
:src=
"userAvatar"
class=
"flex-shrink-0"
>
<el-avatar
:size=
"48"
:src=
"userAvatar"
class=
"flex-shrink-0"
>
<el-icon><User
/></el-icon>
<el-icon>
<User
/>
</el-icon>
</el-avatar>
</el-avatar>
<!-- 输入区域 -->
<!-- 输入区域 -->
<div
class=
"flex-1"
>
<div
class=
"flex-1"
>
<!-- 话题标签输入 -->
<!-- 话题标签输入 -->
<div
class=
"mb-4"
>
<div
class=
"mb-4"
>
<el-input
<el-input
v-model=
"form.title"
:placeholder=
"textMap[type].title"
class=
"tag-input"
clearable
/>
v-model=
"form.title"
:placeholder=
"textMap[type].title"
class=
"tag-input"
clearable
/>
</div>
</div>
<!-- 主要内容输入 -->
<!-- 主要内容输入 -->
<div
class=
"relative mb-3"
>
<div
class=
"relative mb-3"
>
<el-input
<el-input
type=
"textarea"
:placeholder=
"textMap[type].content"
:rows=
"6"
:maxlength=
"maxLength"
type=
"textarea"
show-word-limit
resize=
"none"
class=
"main-textarea"
v-model=
"form.content"
/>
:placeholder=
"textMap[type].content"
:rows=
"6"
:maxlength=
"500"
show-word-limit
resize=
"none"
class=
"main-textarea"
v-model=
"form.content"
/>
<!-- 字符计数 -->
<!-- 字符计数 -->
<!--
<div
class=
"absolute bottom-3 right-3 text-xs text-gray-400"
>
1/30
</div>
-->
<!--
<div
class=
"absolute bottom-3 right-3 text-xs text-gray-400"
>
1/30
</div>
-->
</div>
</div>
...
@@ -38,12 +27,10 @@
...
@@ -38,12 +27,10 @@
<div
class=
"mb-2"
>
<div
class=
"mb-2"
>
<!-- 选择的标签内容 -->
<!-- 选择的标签内容 -->
<div
class=
"flex items-center gap-2"
>
<div
class=
"flex items-center gap-2"
>
<span
v-if=
"mainTagText"
class=
"text-sm text-gray-500"
<span
v-if=
"mainTagText"
class=
"text-sm text-gray-500"
>
主标签:
>
主标签:
<el-tag>
{{
mainTagText
}}
</el-tag>
<el-tag>
{{
mainTagText
}}
</el-tag>
</span>
</span>
<span
v-if=
"subTagTextList.length > 0"
class=
"text-sm text-gray-500"
<span
v-if=
"subTagTextList.length > 0"
class=
"text-sm text-gray-500"
>
副标签:
>
副标签:
<el-tag
class=
"mr-2"
v-for=
"tag in subTagTextList"
:key=
"tag"
>
{{
tag
}}
</el-tag>
<el-tag
class=
"mr-2"
v-for=
"tag in subTagTextList"
:key=
"tag"
>
{{
tag
}}
</el-tag>
</span>
</span>
</div>
</div>
...
@@ -51,24 +38,15 @@
...
@@ -51,24 +38,15 @@
<!-- 图片相关 -->
<!-- 图片相关 -->
<div
v-if=
"form.imgUrl.length"
class=
"flex flex-wrap gap-2"
>
<div
v-if=
"form.imgUrl.length"
class=
"flex flex-wrap gap-2"
>
<!-- 删除图片 -->
<!-- 删除图片 -->
<div
<div
class=
"relative w-20 h-20 rounded-lg overflow-hidden group"
v-for=
"img in form.imgUrl"
:key=
"img"
>
class=
"relative w-20 h-20 rounded-lg overflow-hidden group"
v-for=
"img in form.imgUrl"
:key=
"img"
>
<div
<div
class=
"absolute top-1 right-1 z-10 w-5 h-5 flex items-center justify-center bg-black/60 rounded-full cursor-pointer opacity-0 group-hover:opacity-100 transition-all duration-200 hover:bg-black/80 hover:scale-110"
class=
"absolute top-1 right-1 z-10 w-5 h-5 flex items-center justify-center bg-black/60 rounded-full cursor-pointer opacity-0 group-hover:opacity-100 transition-all duration-200 hover:bg-black/80 hover:scale-110"
@
click=
"handleDeleteImg(img)"
@
click=
"handleDeleteImg(img)"
>
>
<el-icon
class=
"text-white text-xs"
>
<el-icon
class=
"text-white text-xs"
>
<Close
/>
<Close
/>
</el-icon>
</el-icon>
</div>
</div>
<el-image
<el-image
:src=
"img"
class=
"w-full h-full rounded-lg border border-gray-200"
fit=
"cover"
/>
:src=
"img"
class=
"w-full h-full rounded-lg border border-gray-200"
fit=
"cover"
/>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -79,27 +57,23 @@
...
@@ -79,27 +57,23 @@
<!-- 左侧工具按钮 -->
<!-- 左侧工具按钮 -->
<div
class=
"flex items-center gap-1"
>
<div
class=
"flex items-center gap-1"
>
<el-tooltip
content=
"添加标签"
placement=
"top"
:visible=
"visibleTagTooltip"
>
<el-tooltip
content=
"添加标签"
placement=
"top"
:visible=
"visibleTagTooltip"
>
<el-button
<el-button
ref=
"tagButtonRef"
text
ref=
"tagButtonRef"
class=
"w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg"
@
click=
"handleAddTag"
text
@
mouseenter=
"visibleTagTooltip = true"
@
mouseleave=
"visibleTagTooltip = false"
>
class=
"w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg"
<el-icon
size=
"18"
>
@
click=
"handleAddTag"
<CollectionTag
/>
@
mouseenter=
"visibleTagTooltip = true"
</el-icon>
@
mouseleave=
"visibleTagTooltip = false"
>
<el-icon
size=
"18"
><CollectionTag
/></el-icon>
</el-button>
</el-button>
</el-tooltip>
</el-tooltip>
<!-- 隐藏上传文件的input -->
<!-- 隐藏上传文件的input -->
<input
type=
"file"
class=
"hidden"
ref=
"fileInputRef"
@
change=
"handleFileChange"
/>
<input
type=
"file"
class=
"hidden"
ref=
"fileInputRef"
@
change=
"handleFileChange"
/>
<el-tooltip
content=
"添加图片"
placement=
"top"
>
<el-tooltip
content=
"添加图片"
placement=
"top"
>
<el-button
<el-button
text
class=
"w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg"
text
@
click=
"fileInputRef?.click()"
>
class=
"w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg"
<el-icon
size=
"18"
>
@
click=
"fileInputRef?.click()"
<Picture
/>
>
</el-icon>
<el-icon
size=
"18"
><Picture
/></el-icon>
</el-button>
</el-button>
</el-tooltip>
</el-tooltip>
...
@@ -111,7 +85,7 @@
...
@@ -111,7 +85,7 @@
<el-icon
size=
"18"
><VideoPlay
/></el-icon>
<el-icon
size=
"18"
><VideoPlay
/></el-icon>
</el-button>
</el-button>
</el-tooltip>
</el-tooltip>
<el-tooltip
content=
"添加附件"
placement=
"top"
>
<el-tooltip
content=
"添加附件"
placement=
"top"
>
<el-button
<el-button
text
text
...
@@ -126,27 +100,19 @@
...
@@ -126,27 +100,19 @@
<div
class=
"flex items-center gap-3"
>
<div
class=
"flex items-center gap-3"
>
<el-button
<el-button
class=
"px-4 py-2 text-gray-600 hover:text-gray-800 hover:bg-gray-50 rounded-lg border border-gray-200 text-sm"
class=
"px-4 py-2 text-gray-600 hover:text-gray-800 hover:bg-gray-50 rounded-lg border border-gray-200 text-sm"
@
click=
"handlePublish(ReleaseStatusTypeEnum.DRAFT)"
@
click=
"handlePublish(ReleaseStatusTypeEnum.DRAFT)"
>
>
存草稿
存草稿
</el-button>
</el-button>
<el-button
<el-button
type=
"primary"
:disabled=
"disabledSubmit"
type=
"primary"
:disabled=
"disabledSubmit"
class=
"px-6 py-2 bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200"
class=
"px-6 py-2 bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200"
@
click=
"handlePublish(ReleaseStatusTypeEnum.PUBLISH)"
@
click=
"handlePublish(ReleaseStatusTypeEnum.PUBLISH)"
>
>
发布
{{
type
===
ArticleTypeEnum
.
QUESTION
?
'问题'
:
'实践'
}}
发布
{{
type
===
ArticleTypeEnum
.
QUESTION
?
'问题'
:
'实践'
}}
</el-button>
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
<SelectTagsDialog
<SelectTagsDialog
v-model:mainTagId=
"form.mainTagId"
v-model:tagList=
"form.tagList"
ref=
"selectTagsDialogRef"
/>
v-model:mainTagId=
"form.mainTagId"
v-model:tagList=
"form.tagList"
ref=
"selectTagsDialogRef"
/>
<el-tour
v-model=
"openTour"
:mask=
"false"
placement=
"left-start"
type=
"primary"
>
<el-tour
v-model=
"openTour"
:mask=
"false"
placement=
"left-start"
type=
"primary"
>
<el-tour-step
:target=
"tagButtonRef?.$el"
description=
"在这里选择标签"
placement=
"top"
/>
<el-tour-step
:target=
"tagButtonRef?.$el"
description=
"在这里选择标签"
placement=
"top"
/>
...
@@ -168,13 +134,13 @@ import type { AddOrUpdatePracticeDto } from '@/api'
...
@@ -168,13 +134,13 @@ import type { AddOrUpdatePracticeDto } from '@/api'
import
type
{
BooleanFlag
}
from
'@/constants'
import
type
{
BooleanFlag
}
from
'@/constants'
import
type
{
ElButton
}
from
'element-plus'
import
type
{
ElButton
}
from
'element-plus'
import
{
useAnimate
}
from
'@vueuse/core'
import
{
useAnimate
}
from
'@vueuse/core'
import
{
isVisible
}
from
'element-plus/es/utils/index.mjs'
type
ArticleType
=
ArticleTypeEnum
.
QUESTION
|
ArticleTypeEnum
.
PRACTICE
type
ArticleType
=
ArticleTypeEnum
.
QUESTION
|
ArticleTypeEnum
.
PRACTICE
const
{
type
,
isReal
}
=
defineProps
<
{
const
{
type
,
isReal
,
maxLength
=
500
}
=
defineProps
<
{
type
:
ArticleType
type
:
ArticleType
isReal
:
BooleanFlag
isReal
:
BooleanFlag
maxLength
?:
number
}
>
()
}
>
()
const
textMap
:
Record
<
const
textMap
:
Record
<
...
...
src/layoutCulture/components/practiceForm.tsx
View file @
7bdc7b3d
...
@@ -23,7 +23,6 @@ export default defineComponent((_, { expose }) => {
...
@@ -23,7 +23,6 @@ export default defineComponent((_, { expose }) => {
const
rules
=
{
const
rules
=
{
title
:
[{
required
:
true
,
message
:
'请输入实践标题'
,
trigger
:
'blur'
}],
title
:
[{
required
:
true
,
message
:
'请输入实践标题'
,
trigger
:
'blur'
}],
content
:
[{
required
:
true
,
message
:
'请输入实践内容'
,
trigger
:
'blur'
}],
content
:
[{
required
:
true
,
message
:
'请输入实践内容'
,
trigger
:
'blur'
}],
imgUrl
:
[{
required
:
true
,
message
:
'请上传实践图片'
,
trigger
:
'change'
}],
releaseStatus
:
[{
required
:
true
,
message
:
'请选择发布时间'
,
trigger
:
'blur'
}],
releaseStatus
:
[{
required
:
true
,
message
:
'请选择发布时间'
,
trigger
:
'blur'
}],
mainTagId
:
[{
required
:
true
,
message
:
'请选择主标签'
,
trigger
:
'blur'
}],
mainTagId
:
[{
required
:
true
,
message
:
'请选择主标签'
,
trigger
:
'blur'
}],
sendType
:
[{
required
:
true
,
message
:
'请选择发布类型'
,
trigger
:
'blur'
}],
sendType
:
[{
required
:
true
,
message
:
'请选择发布类型'
,
trigger
:
'blur'
}],
...
@@ -98,7 +97,7 @@ export default defineComponent((_, { expose }) => {
...
@@ -98,7 +97,7 @@ export default defineComponent((_, { expose }) => {
class=
"content-input"
class=
"content-input"
/>
/>
</
el
-
form
-
item
>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"图片"
prop=
"imgUrl"
>
<
el
-
form
-
item
label=
"图片"
>
{
/* @ts-ignore */
}
{
/* @ts-ignore */
}
<
UploadFile
v
-
model=
{
form
.
value
.
imgUrl
}
/>
<
UploadFile
v
-
model=
{
form
.
value
.
imgUrl
}
/>
</
el
-
form
-
item
>
</
el
-
form
-
item
>
...
...
src/views/homePage/yaTab/components/practiceList.vue
View file @
7bdc7b3d
<
template
>
<
template
>
<div>
<div>
<!-- 发布区域 -->
<!-- 发布区域 -->
<PublishPractice
:type=
"ArticleTypeEnum.PRACTICE"
:isReal=
"1"
/>
<PublishPractice
:type=
"ArticleTypeEnum.PRACTICE"
:isReal=
"1"
:maxLength=
"2000"
/>
<!-- 标签导航 -->
<!-- 标签导航 -->
<div
class=
"bg-white p-4 mb-6 rounded-lg shadow-sm"
>
<div
class=
"bg-white p-4 mb-6 rounded-lg shadow-sm"
>
<div
class=
"flex flex-wrap gap-2 mb-2"
>
<div
class=
"flex flex-wrap gap-2 mb-2"
>
<el-tag
<el-tag
v-for=
"tag in filterOptions"
:key=
"tag.id"
v-for=
"tag in filterOptions"
:key=
"tag.id"
:type=
"tag.id === searchParams.sortLogic ? 'primary' : 'info'"
:type=
"tag.id === searchParams.sortLogic ? 'primary' : 'info'"
:effect=
"tag.id === searchParams.sortLogic ? 'dark' : 'plain'"
:effect=
"tag.id === searchParams.sortLogic ? 'dark' : 'plain'"
class=
"cursor-pointer"
class=
"cursor-pointer"
@
click=
"toggleFilter(tag.id)"
>
@
click=
"toggleFilter(tag.id)"
>
{{
tag
.
title
}}
{{
tag
.
title
}}
</el-tag>
</el-tag>
</div>
</div>
<div
class=
"flex flex-wrap gap-2"
>
<div
class=
"flex flex-wrap gap-2"
>
<el-tag
<el-tag
v-for=
"tag in tagList"
:key=
"tag.id"
v-for=
"tag in tagList"
:key=
"tag.id"
:type=
"searchParams.tagIdList?.includes(tag.id) ? 'primary' : 'info'"
:type=
"searchParams.tagIdList?.includes(tag.id) ? 'primary' : 'info'"
:effect=
"searchParams.tagIdList?.includes(tag.id) ? 'dark' : 'plain'"
:effect=
"searchParams.tagIdList?.includes(tag.id) ? 'dark' : 'plain'"
class=
"cursor-pointer"
class=
"cursor-pointer"
@
click=
"toggleTag(tag.id)"
>
@
click=
"toggleTag(tag.id)"
>
{{
tag
.
title
}}
{{
tag
.
title
}}
</el-tag>
</el-tag>
</div>
</div>
...
@@ -41,53 +33,40 @@
...
@@ -41,53 +33,40 @@
{{
filterText
}}
{{
filterText
}}
</h2>
</h2>
</div>
</div>
<div
<div
class=
"text-#999 cursor-pointer text-sm"
@
click=
"
class=
"text-#999 cursor-pointer text-sm"
router.push(
{
@
click=
"
path: '/searchPage',
router.push(
{
query: {
path: '/searchPage',
type: ArticleTypeEnum.PRACTICE,
query: {
},
type: ArticleTypeEnum.PRACTICE,
})
},
">
})
"
>
查看更多 >>
查看更多 >>
</div>
</div>
</div>
</div>
<el-divider
class=
"my-1!"
/>
<div
class=
"divide-y bg-#fff"
>
<div
class=
"divide-y bg-#fff"
>
<div
<div
@
click=
"openArticleDetail(item.id)"
v-for=
"item in list"
:key=
"item.id"
@
click=
"openArticleDetail(item.id)"
class=
"p-4 hover:bg-gray-50 transition-colors cursor-pointer pl-8"
>
v-for=
"item in list"
<div
class=
"flex gap-3 items-center h-100%"
style=
"border-bottom: 1.5px solid #ddd;"
>
:key=
"item.id"
class=
"p-4 hover:bg-gray-50 transition-colors cursor-pointer"
>
<div
class=
"flex gap-3 items-center"
>
<!-- 左侧内容 -->
<!-- 左侧内容 -->
<div
class=
"flex-1"
>
<div
class=
"flex-1"
>
<h
2
class=
"font-medium text-gray-900 mb-2 leading-relaxed line-clamp-1
"
>
<h
1
class=
"font-medium text-gray-900 mb-2 leading-relaxed line-clamp-1 text-18px
"
>
{{
item
.
title
}}
{{
item
.
title
}}
</h
2
>
</h
1
>
<!-- 带图片的内容 -->
<!-- 带图片的内容 -->
<div
class=
"flex gap-3 mb-3"
>
<div
class=
"flex gap-3 mb-3 align-center"
style=
"border-right: 1.5px solid #ddd;"
>
<img
<img
v-if=
"item.faceUrl"
:src=
"item.faceUrl"
:alt=
"item.title"
v-if=
"item.faceUrl"
class=
"w-40 h-25 object-cover rounded-lg flex-shrink-0"
/>
:src=
"item.faceUrl"
<div
class=
"flex-1 mr-4"
>
:alt=
"item.title"
<div
class=
"text-gray-600 text-sm leading-relaxed line-clamp-4"
>
class=
"w-20 h-20 object-cover rounded-lg flex-shrink-0"
/>
<div
class=
"flex-1"
>
<div
class=
"text-gray-600 text-sm leading-relaxed line-clamp-3"
>
{{
item
.
content
}}
{{
item
.
content
}}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 互动数据 -->
<!-- 互动数据 -->
<div
class=
"flex items-center gap-
4 text-gray-400 text-sm
"
>
<div
class=
"flex items-center gap-
5 text-gray-400 text-base mb-3
"
>
<div
class=
"flex items-center gap-1"
>
<div
class=
"flex items-center gap-1"
>
<el-icon
class=
"text-sm"
>
<el-icon
class=
"text-sm"
>
<View
/>
<View
/>
...
@@ -100,7 +79,7 @@
...
@@ -100,7 +79,7 @@
</el-icon>
</el-icon>
<span>
{{
item
.
replyCount
}}
</span>
<span>
{{
item
.
replyCount
}}
</span>
</div>
</div>
<div
class=
"flex items-center gap-1"
>
<div
class=
"flex items-center gap-1
mr-2
"
>
<el-icon
class=
"text-sm"
>
<el-icon
class=
"text-sm"
>
<Star
/>
<Star
/>
</el-icon>
</el-icon>
...
@@ -109,11 +88,13 @@
...
@@ -109,11 +88,13 @@
<div>
{{
dayjs
(
item
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm'
)
}}
</div>
<div>
{{
dayjs
(
item
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm'
)
}}
</div>
</div>
</div>
</div>
</div>
<!-- 加一个el-divider -->
<el-divider
class=
"my-1! h-100%!"
direction=
"vertical"
/>
<!-- 右侧头像 -->
<!-- 右侧头像 -->
<div
class=
"flex flex-col items-center gap-1 flex-shrink-0"
>
<div
class=
"flex flex-col items-center gap-1 flex-shrink-0
pr-8
"
>
<el-avatar
:size=
"4
0
"
:src=
"item.showAvatar"
/>
<el-avatar
:size=
"4
5
"
:src=
"item.showAvatar"
/>
<div
class=
"text-xs text-gray-
500
"
>
{{
item
.
showName
}}
</div>
<div
class=
"text-xs text-gray-
600 mt-2
"
>
{{
item
.
showName
}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -130,23 +111,14 @@
...
@@ -130,23 +111,14 @@
<!-- 右侧:分页器 -->
<!-- 右侧:分页器 -->
<div
class=
"right"
>
<div
class=
"right"
>
<div
<div
class=
"pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-3"
>
class=
"pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-3"
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
>
:page-sizes=
"[5, 20, 1]"
layout=
"prev, pager, next, jumper, total"
:total=
"total"
<el-pagination
class=
"custom-pagination"
@
current-change=
"
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:page-sizes=
"[5, 20, 1]"
layout=
"prev, pager, next, jumper, total"
:total=
"total"
class=
"custom-pagination"
@
current-change=
"
(e) =>
{
(e) =>
{
;(handleBackTop(), goToPage(e))
;
(handleBackTop(), goToPage(e))
}
}
"
" @size-change="changePageSize" />
@size-change="changePageSize"
/>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment