Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
corporate-culture-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
王立鹏
corporate-culture-qd
Commits
dacd3221
Commit
dacd3221
authored
Jul 23, 2026
by
lijiabin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【需求 23684】feat: 完善文章推荐和最新展示配置
parent
b2cf34ee
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
123 additions
and
6 deletions
+123
-6
index.ts
src/api/article/index.ts
+25
-0
types.ts
src/api/article/types.ts
+17
-0
index.vue
src/components/common/ArticleContent/index.vue
+60
-5
index.vue
src/views/backend/contentsMenu/videoManage/index.vue
+21
-1
No files found.
src/api/article/index.ts
View file @
dacd3221
...
...
@@ -19,6 +19,9 @@ import type {
SearchMoreVideoItemDto
,
SecondCommentItemDto
,
UpdateArticleRecommendAndSortDto
,
RelatedColumnItemDto
,
RelatedColumnParams
,
UpdateArticleShowLatestDto
,
}
from
'./types'
import
type
{
BackendServicePageResult
,
PageSearchParams
}
from
'@/utils/request/types'
import
{
SpecificVideoRewardEnum
,
BooleanFlag
}
from
'@/constants'
...
...
@@ -396,3 +399,25 @@ export const getAtUserList = (
data
,
})
}
/**
* 根据标签获取专栏相关推荐
*/
export
const
getRelatedColumnList
=
(
data
:
RelatedColumnParams
)
=>
{
return
service
.
request
<
RelatedColumnItemDto
[]
>
({
url
:
'/api/cultureArticle/relatedByTag'
,
method
:
'POST'
,
data
,
})
}
/**
* 修改视频是否在首页最新列表展示
*/
export
const
updateArticleShowLatest
=
(
data
:
UpdateArticleShowLatestDto
)
=>
{
return
service
.
request
<
boolean
>
({
url
:
'/api/cultureArticle/updateShowLatest'
,
method
:
'POST'
,
data
,
})
}
src/api/article/types.ts
View file @
dacd3221
...
...
@@ -125,6 +125,7 @@ export interface AddOrUpdateVideoDto {
mainTagId
:
string
|
number
tagList
:
{
tagId
:
number
;
sort
:
number
}[]
|
number
[]
relateColumnId
?:
number
isShowLatest
?:
BooleanFlag
}
/**
...
...
@@ -212,6 +213,7 @@ export interface ArticleItemDto {
recommendSort
:
number
isOfficialAccount
:
BooleanFlag
deptId
:
string
isShowLatest
?:
BooleanFlag
}
/**
...
...
@@ -502,3 +504,18 @@ export interface AtUserInfoDto {
userId
:
number
version
:
number
}
export
interface
RelatedColumnParams
{
articleId
:
number
tagId
:
number
}
export
interface
RelatedColumnItemDto
{
id
:
number
title
:
string
}
export
interface
UpdateArticleShowLatestDto
{
articleId
:
number
isShowLatest
:
BooleanFlag
}
src/components/common/ArticleContent/index.vue
View file @
dacd3221
...
...
@@ -232,13 +232,41 @@
</div>
<!-- 标签 -->
<div
class=
"flex flex-wrap gap-2 mt-6"
>
<
spa
n
v-for=
"
item
in articleDetail?.tagNameList"
<
butto
n
v-for=
"
(item, index)
in articleDetail?.tagNameList"
:key=
"item"
class=
"px-3 py-1 text-sm bg-gradient-to-r from-cyan-100 to-blue-100 text-cyan-600 rounded-full hover:shadow-md transition-all cursor-pointer"
type=
"button"
:disabled=
"!canLoadRelatedColumns"
:class=
"[
'px-3 py-1 text-sm bg-gradient-to-r from-cyan-100 to-blue-100 text-cyan-600 rounded-full transition-all',
canLoadRelatedColumns ? 'cursor-pointer hover:shadow-md' : 'cursor-default',
activeKeyword === item ? 'ring-2 ring-cyan-400' : '',
]"
@
click=
"handleTagClick(item, articleDetail.tagIdList[index]!)"
>
#{{ item }}
</span>
</button>
</div>
<div
v-if=
"canLoadRelatedColumns && activeKeyword"
v-loading=
"relatedColumnLoading"
class=
"mt-4 min-h-24 border-t border-gray-100 pt-4"
>
<h2
class=
"mb-3 text-sm font-semibold text-gray-700"
>
相关推荐
</h2>
<ul
v-if=
"relatedColumnList.length"
class=
"space-y-2"
>
<li
v-for=
"(item, index) in relatedColumnList"
:key=
"item.id"
>
<button
type=
"button"
class=
"flex w-full items-center gap-2 text-left text-sm text-gray-600 hover:text-blue-600 cursor-pointer"
@
click=
"router.push(`/articleDetail/${item.id}`)"
>
<span
class=
"flex-shrink-0 text-gray-400"
>
{{ index + 1 }}.
</span>
<span
class=
"truncate"
>
{{ item.title }}
</span>
</button>
</li>
</ul>
<p
v-else-if=
"!relatedColumnLoading"
class=
"text-sm text-gray-400"
>
暂无相关推荐
</p>
</div>
</div>
</template>
...
...
@@ -258,7 +286,7 @@
<
script
setup
lang=
"ts"
>
import
dayjs
from
'dayjs'
import
type
{
Article
ItemDto
}
from
'@/api'
import
{
getRelatedColumnList
,
type
ArticleItemDto
,
type
RelatedColumn
ItemDto
}
from
'@/api'
import
{
articleTypeListOptions
,
ArticleTypeEnum
,
VideoPositionEnum
}
from
'@/constants'
import
ActionMore
from
'@/components/common/ActionMore/index.vue'
import
SendMessageDialog
from
'@/components/common/SendMessageDialog/index.vue'
...
...
@@ -290,6 +318,33 @@ const isReal = computed(() => {
const
loading
=
computed
(()
=>
!
articleDetail
.
title
)
// 只有专栏才能点击标签 获取相关推送
const
canLoadRelatedColumns
=
computed
(
()
=>
articleDetail
.
type
===
ArticleTypeEnum
.
COLUMN
&&
!
isAudit
,
)
const
activeKeyword
=
ref
(
''
)
const
relatedColumnLoading
=
ref
(
false
)
const
relatedColumnList
=
ref
<
RelatedColumnItemDto
[]
>
([])
const
handleTagClick
=
async
(
keyword
:
string
,
tagId
:
number
)
=>
{
if
(
!
canLoadRelatedColumns
.
value
)
return
activeKeyword
.
value
=
keyword
relatedColumnList
.
value
=
[]
relatedColumnLoading
.
value
=
true
try
{
const
{
data
}
=
await
getRelatedColumnList
({
articleId
:
articleDetail
.
id
,
tagId
,
})
relatedColumnList
.
value
=
data
}
catch
{
relatedColumnList
.
value
=
[]
}
finally
{
relatedColumnLoading
.
value
=
false
}
}
// 是否是作者
const
isAuthor
=
computed
(()
=>
{
return
articleDetail
.
createUserId
===
userInfo
.
value
.
userId
...
...
src/views/backend/contentsMenu/videoManage/index.vue
View file @
dacd3221
...
...
@@ -2,7 +2,7 @@
import
{
Search
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
addOrUpdateColumn
}
from
'@/api/backend'
import
{
getArticleList
,
updateArticleRecommendAndSort
}
from
'@/api'
import
{
getArticleList
,
updateArticleRecommendAndSort
,
updateArticleShowLatest
}
from
'@/api'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendColumnListItemDto
,
AddOrUpdateColumnDto
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
...
...
@@ -51,6 +51,15 @@ const handleIsRecommendChange = async (val: BooleanFlag, row: ArticleItemDto) =>
refresh
()
}
const
handleIsShowLatestChange
=
async
(
val
:
BooleanFlag
,
row
:
ArticleItemDto
)
=>
{
await
updateArticleShowLatest
({
articleId
:
row
.
id
,
isShowLatest
:
val
,
})
push
.
success
(
'修改成功'
)
refresh
()
}
// 编辑排序
const
handleEditSort
=
async
(
row
:
ArticleItemDto
)
=>
{
const
value
=
await
prompt
({
...
...
@@ -155,6 +164,17 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
</
template
>
</el-table-column>
<el-table-column
prop=
"isShowLatest"
label=
"是否在最新出现"
min-width=
"160"
>
<
template
#
default=
"{ row }"
>
<el-switch
:model-value=
"row.isShowLatest ?? BooleanFlag.YES"
:active-value=
"BooleanFlag.YES"
:inactive-value=
"BooleanFlag.NO"
@
change=
"(val) => handleIsShowLatestChange(val as BooleanFlag, row)"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"是否推荐"
min-width=
"200"
>
<
template
#
header
>
<div
class=
"flex items-center gap-2"
>
...
...
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