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
4a950630
Commit
4a950630
authored
Nov 21, 2025
by
lijiabin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【需求 17679】 wip: 继续完善页面
parent
2610f8e0
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
499 additions
and
72 deletions
+499
-72
components.d.ts
components.d.ts
+2
-0
types.ts
src/api/article/types.ts
+4
-2
index.ts
src/api/practice/index.ts
+12
-2
types.ts
src/api/practice/types.ts
+26
-2
recommend.png
src/assets/img/culture/recommend.png
+0
-0
index.vue
src/components/common/LoadingComponent/index.vue
+50
-0
colnumForm.tsx
src/layoutCulture/components/colnumForm.tsx
+23
-5
interviewForm.tsx
src/layoutCulture/components/interviewForm.tsx
+29
-10
postForm.tsx
src/layoutCulture/components/postForm.tsx
+5
-0
practiceForm.tsx
src/layoutCulture/components/practiceForm.tsx
+7
-1
publishDialog.vue
src/layoutCulture/components/publishDialog.vue
+50
-13
index.vue
src/layoutCulture/index.vue
+2
-2
index.ts
src/router/index.ts
+6
-0
recommendList.vue
src/views/homePage/homeTab/components/recommendList.vue
+2
-1
videoList.vue
src/views/homePage/homeTab/components/videoList.vue
+2
-2
index.vue
src/views/homePage/homeTab/index.vue
+17
-16
columnList.vue
src/views/homePage/yaTab/components/columnList.vue
+7
-6
interviewList.vue
src/views/homePage/yaTab/components/interviewList.vue
+8
-7
practiceList.vue
src/views/homePage/yaTab/components/practiceList.vue
+0
-0
index.vue
src/views/publishVideo/index.vue
+7
-1
index.vue
src/views/searchPage/index.vue
+238
-0
vite.config.ts
vite.config.ts
+2
-2
No files found.
components.d.ts
View file @
4a950630
...
...
@@ -53,6 +53,7 @@ declare module 'vue' {
IconEcosystem
:
typeof
import
(
'./src/components/icons/IconEcosystem.vue'
)[
'default'
]
IconSupport
:
typeof
import
(
'./src/components/icons/IconSupport.vue'
)[
'default'
]
IconTooling
:
typeof
import
(
'./src/components/icons/IconTooling.vue'
)[
'default'
]
LoadingComponent
:
typeof
import
(
'./src/components/common/LoadingComponent/index.vue'
)[
'default'
]
RouterLink
:
typeof
import
(
'vue-router'
)[
'RouterLink'
]
RouterView
:
typeof
import
(
'vue-router'
)[
'RouterView'
]
SelectTags
:
typeof
import
(
'./src/components/common/SelectTags/index.vue'
)[
'default'
]
...
...
@@ -108,6 +109,7 @@ declare global {
const
IconEcosystem
:
typeof
import
(
'./src/components/icons/IconEcosystem.vue'
)[
'default'
]
const
IconSupport
:
typeof
import
(
'./src/components/icons/IconSupport.vue'
)[
'default'
]
const
IconTooling
:
typeof
import
(
'./src/components/icons/IconTooling.vue'
)[
'default'
]
const
LoadingComponent
:
typeof
import
(
'./src/components/common/LoadingComponent/index.vue'
)[
'default'
]
const
RouterLink
:
typeof
import
(
'vue-router'
)[
'RouterLink'
]
const
RouterView
:
typeof
import
(
'vue-router'
)[
'RouterView'
]
const
SelectTags
:
typeof
import
(
'./src/components/common/SelectTags/index.vue'
)[
'default'
]
...
...
src/api/article/types.ts
View file @
4a950630
...
...
@@ -42,10 +42,11 @@ interface AddOrUpdateColumnBase {
faceUrl
?:
string
imgUrl
?:
string
// 关联的专栏栏目
relateColumnId
:
number
relateColumnId
?
:
number
mainTagId
:
string
isRelateColleague
:
BooleanFlag
sendTime
?:
string
isRecommend
:
BooleanFlag
}
/**
...
...
@@ -72,9 +73,10 @@ export interface AddOrUpdateInterviewBase {
faceUrl
?:
string
imgUrl
?:
string
// 关联的专访栏目
relateColumnId
:
number
relateColumnId
?
:
number
mainTagId
:
string
sendTime
?:
string
isRecommend
:
BooleanFlag
}
export
interface
AddOrUpdateInterviewForm
extends
AddOrUpdateInterviewBase
{
...
...
src/api/practice/index.ts
View file @
4a950630
import
service
from
'@/utils/request/index'
import
type
{
AddOrUpdatePracticeDto
,
ArticleItemDto
,
ArticleSearchParams
}
from
'./types'
import
type
{
AddOrUpdatePracticeDto
,
PracticeSearchParams
,
PracticeItemDto
}
from
'./types'
import
type
{
BackendServicePageResult
}
from
'@/utils/request/types'
import
{
ArticleTypeEnum
}
from
'@/constants'
// 关于实践相关接口
...
...
@@ -15,3 +14,14 @@ export const addOrUpdatePractice = (data: AddOrUpdatePracticeDto) => {
data
,
})
}
/**
* 实践列表接口
*/
export
const
getPracticeList
=
(
data
:
PracticeSearchParams
)
=>
{
return
service
.
request
<
BackendServicePageResult
<
PracticeItemDto
>>
({
url
:
'/api/yaCulture/practiceList'
,
method
:
'POST'
,
data
,
})
}
src/api/practice/types.ts
View file @
4a950630
...
...
@@ -20,8 +20,8 @@ export interface AddOrUpdatePracticeDto {
/**
* 搜索文章的参数
*/
export
interface
Articl
eSearchParams
extends
PageSearchParams
{
type
?:
ArticleTypeEnum
export
interface
Practic
eSearchParams
extends
PageSearchParams
{
sortLogic
?:
number
}
/**
...
...
@@ -90,3 +90,27 @@ export interface ArticleItemDto {
replyCount
:
number
hasPraised
:
BooleanFlag
}
/**
* 实践列表item
*/
export
interface
PracticeItemDto
{
collectionCount
:
number
content
:
string
createTime
:
number
createUserId
:
number
description
:
string
faceUrl
:
string
hasPraised
:
boolean
id
:
number
isRecommend
:
BooleanFlag
praiseCount
:
number
releaseStatus
:
ReleaseStatusTypeEnum
replyCount
:
number
showAvatar
:
string
showName
:
string
tagNameList
:
string
[]
title
:
string
type
:
ArticleTypeEnum
.
PRACTICE
viewCount
:
number
}
src/assets/img/culture/recommend.png
0 → 100644
View file @
4a950630
1.87 KB
src/components/common/LoadingComponent/index.vue
0 → 100644
View file @
4a950630
<!-- LoadingComponent.vue -->
<
template
>
<div
class=
"loading-container"
>
<div
class=
"loading-spinner"
></div>
<span
v-if=
"showText"
class=
"loading-text"
>
{{
text
}}
</span>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
interface
Props
{
text
?:
string
showText
?:
boolean
}
withDefaults
(
defineProps
<
Props
>
(),
{
text
:
'加载中...'
,
showText
:
true
,
})
</
script
>
<
style
scoped
>
.loading-container
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
padding
:
40px
20px
;
gap
:
12px
;
}
.loading-spinner
{
width
:
32px
;
height
:
32px
;
border
:
3px
solid
#f0f0f0
;
border-top-color
:
#409eff
;
border-radius
:
50%
;
animation
:
spin
0.8s
linear
infinite
;
}
.loading-text
{
font-size
:
14px
;
color
:
#909399
;
}
@keyframes
spin
{
to
{
transform
:
rotate
(
360deg
);
}
}
</
style
>
src/layoutCulture/components/colnumForm.tsx
View file @
4a950630
...
...
@@ -24,8 +24,9 @@ export default defineComponent((_, { expose }) => {
sendType
:
SendTypeEnum
.
IMMEDIATE
,
sendTime
:
''
,
isRelateColleague
:
BooleanFlag
.
NO
,
relateColumnId
:
0
,
relateColumnId
:
undefined
,
type
:
ArticleTypeEnum
.
COLUMN
,
isRecommend
:
BooleanFlag
.
NO
,
})
const
formRef
=
ref
<
InstanceType
<
typeof
ElForm
>>
()
const
rules
=
{
...
...
@@ -38,6 +39,7 @@ export default defineComponent((_, { expose }) => {
relateColumnId
:
[
{
required
:
true
,
message
:
'请选择专栏栏目'
,
trigger
:
'blur'
,
type
:
'number'
,
min
:
1
},
],
isRecommend
:
[{
required
:
true
,
message
:
'请选择是否推荐'
,
trigger
:
'blur'
}],
}
const
transformForm
=
(
releaseStatus
:
ReleaseStatusTypeEnum
):
AddOrUpdateColumnDto
=>
{
...
...
@@ -113,11 +115,11 @@ export default defineComponent((_, { expose }) => {
<
UploadFile
v
-
model=
{
form
.
value
.
imgUrl
}
/>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"专栏栏目选择"
prop=
"relateColumnId"
>
<
el
-
radio
-
group
v
-
model=
{
form
.
value
.
relateColumnId
}
>
<
el
-
select
v
-
model=
{
form
.
value
.
relateColumnId
}
placeholder=
"请选择专栏栏目"
>
{
columnList
.
value
.
map
((
item
)
=>
(
<
el
-
radio
value=
{
item
.
id
}
>
{
item
.
title
}
</
el
-
radio
>
<
el
-
option
value=
{
item
.
id
}
>
{
item
.
title
}
</
el
-
option
>
))
}
</
el
-
radio
-
group
>
</
el
-
select
>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"主标签"
prop=
"mainTagId"
>
{
{
...
...
@@ -126,7 +128,7 @@ export default defineComponent((_, { expose }) => {
label
:
()
=>
(
// <el-tooltip content="主标签最多选1个" placement="top">
<
span
class=
"cursor-pointer"
>
副
标签
主
标签
{
/* <el-icon class="ml-1">
<InfoFilled />
</el-icon> */
}
...
...
@@ -167,6 +169,16 @@ export default defineComponent((_, { expose }) => {
</
el
-
radio
>
</
el
-
radio
-
group
>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"是否推荐"
prop=
"isRecommend"
>
<
el
-
radio
-
group
v
-
model=
{
form
.
value
.
isRecommend
}
class=
"radio-group"
>
<
el
-
radio
value=
{
BooleanFlag
.
YES
}
class=
"radio-item immediate"
>
是
</
el
-
radio
>
<
el
-
radio
value=
{
BooleanFlag
.
NO
}
class=
"radio-item scheduled"
>
否
</
el
-
radio
>
</
el
-
radio
-
group
>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"发布类型"
prop=
"sendType"
>
<
el
-
radio
-
group
v
-
model=
{
form
.
value
.
sendType
}
class=
"radio-group"
>
<
el
-
radio
value=
{
SendTypeEnum
.
IMMEDIATE
}
class=
"radio-item immediate"
>
...
...
@@ -184,6 +196,12 @@ export default defineComponent((_, { expose }) => {
v
-
model=
{
form
.
value
.
sendTime
}
type=
"datetime"
placeholder=
"请选择发布时间"
// 不能选现在
disabled
-
date=
{
(
time
:
Date
)
=>
{
return
time
.
getTime
()
<
Date
.
now
()
-
1000
*
60
*
60
*
24
}
}
value
-
format=
"X"
style=
{
{
width
:
'250px'
}
}
/>
</
el
-
form
-
item
>
)
}
...
...
src/layoutCulture/components/interviewForm.tsx
View file @
4a950630
import
{
ArticleTypeEnum
,
ReleaseStatusTypeEnum
,
SendTypeEnum
}
from
'@/constants'
import
{
ArticleTypeEnum
,
BooleanFlag
,
ReleaseStatusTypeEnum
,
SendTypeEnum
}
from
'@/constants'
import
UploadFile
from
'@/components/common/UploadFile/index.vue'
import
{
useResetData
}
from
'@/hooks'
import
{
use
ColumnStore
}
from
'@/stores/column
'
import
{
use
InterviewStore
}
from
'@/stores/interview
'
import
{
storeToRefs
}
from
'pinia'
import
type
{
AddOrUpdateInterviewDto
,
AddOrUpdateInterviewForm
}
from
'@/api/article/types'
import
type
{
TagItemDto
}
from
'@/api/tag/types'
export
default
defineComponent
((
_
,
{
expose
})
=>
{
const
columnStore
=
useColumn
Store
()
const
{
columnList
}
=
storeToRefs
(
column
Store
)
const
interviewStore
=
useInterview
Store
()
const
{
interviewList
}
=
storeToRefs
(
interview
Store
)
const
[
form
,
resetForm
]
=
useResetData
<
AddOrUpdateInterviewForm
>
({
title
:
''
,
content
:
''
,
...
...
@@ -22,7 +22,8 @@ export default defineComponent((_, { expose }) => {
sendType
:
SendTypeEnum
.
IMMEDIATE
,
sendTime
:
''
,
type
:
ArticleTypeEnum
.
INTERVIEW
,
relateColumnId
:
0
,
relateColumnId
:
undefined
,
isRecommend
:
BooleanFlag
.
NO
,
})
const
formRef
=
ref
<
InstanceType
<
typeof
ElForm
>>
()
const
rules
=
{
...
...
@@ -35,6 +36,7 @@ export default defineComponent((_, { expose }) => {
relateColumnId
:
[
{
required
:
true
,
message
:
'请选择专访栏目'
,
trigger
:
'blur'
,
type
:
'number'
,
min
:
1
},
],
isRecommend
:
[{
required
:
true
,
message
:
'请选择是否推荐'
,
trigger
:
'blur'
}],
}
const
transformForm
=
(
releaseStatus
:
ReleaseStatusTypeEnum
):
AddOrUpdateInterviewDto
=>
{
...
...
@@ -110,11 +112,11 @@ export default defineComponent((_, { expose }) => {
<
UploadFile
v
-
model=
{
form
.
value
.
imgUrl
}
/>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"专访栏目选择"
prop=
"relateColumnId"
>
<
el
-
radio
-
group
v
-
model=
{
form
.
value
.
relateColumnId
}
>
{
column
List
.
value
.
map
((
item
)
=>
(
<
el
-
radio
value=
{
item
.
id
}
>
{
item
.
title
}
</
el
-
radio
>
<
el
-
select
v
-
model=
{
form
.
value
.
relateColumnId
}
placeholder=
"请选择专访栏目"
>
{
interview
List
.
value
.
map
((
item
)
=>
(
<
el
-
option
value=
{
item
.
id
}
label=
{
item
.
title
}
/
>
))
}
</
el
-
radio
-
group
>
</
el
-
select
>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"主标签"
prop=
"mainTagId"
>
{
{
...
...
@@ -123,7 +125,7 @@ export default defineComponent((_, { expose }) => {
label
:
()
=>
(
// <el-tooltip content="主标签最多选1个" placement="top">
<
span
class=
"cursor-pointer"
>
副
标签
主
标签
{
/* <el-icon class="ml-1">
<InfoFilled />
</el-icon> */
}
...
...
@@ -154,6 +156,17 @@ export default defineComponent((_, { expose }) => {
),
}
}
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"是否推荐"
prop=
"isRecommend"
>
<
el
-
radio
-
group
v
-
model=
{
form
.
value
.
isRecommend
}
class=
"radio-group"
>
<
el
-
radio
value=
{
BooleanFlag
.
YES
}
class=
"radio-item immediate"
>
是
</
el
-
radio
>
<
el
-
radio
value=
{
BooleanFlag
.
NO
}
class=
"radio-item scheduled"
>
否
</
el
-
radio
>
</
el
-
radio
-
group
>
</
el
-
form
-
item
>
<
el
-
form
-
item
label=
"发布类型"
prop=
"sendType"
>
<
el
-
radio
-
group
v
-
model=
{
form
.
value
.
sendType
}
class=
"radio-group"
>
<
el
-
radio
value=
{
SendTypeEnum
.
IMMEDIATE
}
class=
"radio-item immediate"
>
...
...
@@ -171,6 +184,12 @@ export default defineComponent((_, { expose }) => {
v
-
model=
{
form
.
value
.
sendTime
}
type=
"datetime"
placeholder=
"请选择发布时间"
// 不能选现在
disabled
-
date=
{
(
time
:
Date
)
=>
{
return
time
.
getTime
()
<
Date
.
now
()
-
1000
*
60
*
60
*
24
}
}
value
-
format=
"X"
style=
{
{
width
:
'250px'
}
}
/>
</
el
-
form
-
item
>
)
}
...
...
src/layoutCulture/components/postForm.tsx
View file @
4a950630
...
...
@@ -100,7 +100,12 @@ export default defineComponent(
v
-
model=
{
form
.
value
.
sendTime
}
type=
"datetime"
placeholder=
"请选择发布时间"
// 不能选现在
disabled
-
date=
{
(
time
:
Date
)
=>
{
return
time
.
getTime
()
<
Date
.
now
()
-
1000
*
60
*
60
*
24
}
}
value
-
format=
"X"
style=
{
{
width
:
'250px'
}
}
/>
</
el
-
form
-
item
>
)
}
...
...
src/layoutCulture/components/practiceForm.tsx
View file @
4a950630
...
...
@@ -109,7 +109,7 @@ export default defineComponent((_, { expose }) => {
label
:
()
=>
(
// <el-tooltip content="主标签最多选1个" placement="top">
<
span
class=
"cursor-pointer"
>
副
标签
主
标签
{
/* <el-icon class="ml-1">
<InfoFilled />
</el-icon> */
}
...
...
@@ -157,6 +157,12 @@ export default defineComponent((_, { expose }) => {
v
-
model=
{
form
.
value
.
sendTime
}
type=
"datetime"
placeholder=
"请选择发布时间"
// 不能选现在
disabled
-
date=
{
(
time
:
Date
)
=>
{
return
time
.
getTime
()
<
Date
.
now
()
-
1000
*
60
*
60
*
24
}
}
value
-
format=
"X"
style=
{
{
width
:
'250px'
}
}
/>
</
el
-
form
-
item
>
)
}
...
...
src/layoutCulture/components/publishDialog.vue
View file @
4a950630
...
...
@@ -40,47 +40,84 @@ import type { Component } from 'vue'
// import { Plus } from '@element-plus/icons-vue'
import
{
addOrUpdateArticle
,
addOrUpdatePractice
}
from
'@/api'
import
{
ArticleTypeEnum
,
ReleaseStatusTypeEnum
}
from
'@/constants'
import
PostForm
from
'./postForm.tsx'
import
PracticeForm
from
'./practiceForm.tsx'
import
LoadingComponent
from
'@/components/common/LoadingComponent/index.vue'
const
typeMap
:
Record
<
ArticleTypeEnum
,
{
title
:
string
;
component
:
Component
;
api
?:
(
data
:
any
)
=>
Promise
<
any
>
}
>
=
{
[
ArticleTypeEnum
.
VIDEO
]:
{
title
:
'视频'
,
component
:
PostForm
,
component
:
defineAsyncComponent
({
loader
:
()
=>
import
(
'./postForm.tsx'
),
delay
:
200
,
loadingComponent
:
LoadingComponent
,
}),
},
[
ArticleTypeEnum
.
QUESTION
]:
{
title
:
'问题'
,
component
:
PostForm
,
component
:
defineAsyncComponent
({
loader
:
()
=>
import
(
'./postForm.tsx'
),
delay
:
200
,
loadingComponent
:
LoadingComponent
,
}),
},
[
ArticleTypeEnum
.
POST
]:
{
title
:
'帖子'
,
component
:
defineAsyncComponent
(()
=>
import
(
'./postForm.tsx'
)),
component
:
defineAsyncComponent
({
loader
:
async
()
=>
{
const
start
=
Date
.
now
()
const
comp
=
await
import
(
'./postForm.tsx'
)
const
cost
=
Date
.
now
()
-
start
console
.
log
(
'cost'
,
cost
)
const
min
=
1000
// 最低 200ms
if
(
cost
<
min
)
{
await
new
Promise
((
r
)
=>
setTimeout
(
r
,
min
-
cost
))
}
return
comp
},
delay
:
200
,
loadingComponent
:
LoadingComponent
,
}),
api
:
addOrUpdateArticle
,
},
[
ArticleTypeEnum
.
PRACTICE
]:
{
title
:
'实践'
,
component
:
defineAsyncComponent
(()
=>
import
(
'./practiceForm.tsx'
)),
component
:
defineAsyncComponent
({
loader
:
()
=>
import
(
'./practiceForm.tsx'
),
delay
:
200
,
loadingComponent
:
LoadingComponent
,
}),
api
:
addOrUpdatePractice
,
},
[
ArticleTypeEnum
.
COLUMN
]:
{
title
:
'专栏'
,
component
:
defineAsyncComponent
(()
=>
import
(
'./colnumForm.tsx'
)),
component
:
defineAsyncComponent
({
loader
:
()
=>
import
(
'./colnumForm.tsx'
),
delay
:
200
,
loadingComponent
:
LoadingComponent
,
}),
api
:
addOrUpdateArticle
,
},
[
ArticleTypeEnum
.
INTERVIEW
]:
{
title
:
'专访'
,
component
:
defineAsyncComponent
(()
=>
import
(
'./interviewForm.tsx'
)),
component
:
defineAsyncComponent
({
loader
:
()
=>
import
(
'./interviewForm.tsx'
),
delay
:
200
,
loadingComponent
:
LoadingComponent
,
}),
api
:
addOrUpdateArticle
,
},
}
const
dialogTitle
=
computed
(()
=>
'发布'
+
typeMap
[
articleType
.
value
].
title
)
const
formComponentRef
=
useTemplateRef
<
InstanceType
<
typeof
PostForm
|
typeof
PracticeForm
>>
(
'formComponentRef'
)
export
interface
BaseFormExpose
{
resetFields
:
()
=>
void
getValidatedFormData
:
(
releaseStatus
:
ReleaseStatusTypeEnum
)
=>
Promise
<
unknown
>
}
const
formComponentRef
=
useTemplateRef
<
BaseFormExpose
>
(
'formComponentRef'
)
const
currentFormComp
=
computed
(()
=>
{
return
typeMap
[
articleType
.
value
].
component
...
...
@@ -100,7 +137,7 @@ const open = (type: ArticleTypeEnum) => {
// 关闭弹窗
const
close
=
()
=>
{
dialogVisible
.
value
=
false
formComponentRef
.
value
?.
resetFields
()
formComponentRef
?
.
value
?.
resetFields
()
}
const
handleClosed
=
()
=>
{
...
...
src/layoutCulture/index.vue
View file @
4a950630
...
...
@@ -16,8 +16,8 @@
<!-- 搜索框 -->
<div
class=
"flex-1 max-w-sm mx-4 hidden md:block lg:max-w-md lg:mx-6"
>
<el-input
v-model=
"search"
class=
"h-8"
placeholder=
"搜索"
>
<template
#
pre
fix
>
<el-icon
class=
"text-gray-400"
>
<template
#
suf
fix
>
<el-icon
class=
"text-gray-400"
@
click=
"router.push('/searchPage')"
>
<Search
/>
</el-icon>
</
template
>
...
...
src/router/index.ts
View file @
4a950630
...
...
@@ -66,6 +66,12 @@ const routes = [
name
:
'CulturePublishCase'
,
component
:
()
=>
import
(
'@/views/publishCase/index.vue'
),
},
// 搜索页面
{
path
:
'searchPage'
,
name
:
'CultureSearchPage'
,
component
:
()
=>
import
(
'@/views/searchPage/index.vue'
),
},
// 发布文章
// {
// {
...
...
src/views/homePage/homeTab/components/recommendList.vue
View file @
4a950630
...
...
@@ -128,6 +128,7 @@ const { list, total, searchParams, loading, goToPage, changePageSize, refresh }
defaultParams
:
{
sortLogic
:
0
},
defaultCurrent
:
1
,
defaultSize
:
5
,
immediate
:
false
,
},
)
const
tabsRef
=
inject
(
TABS_REF_KEY
)
...
...
@@ -135,7 +136,7 @@ const tabsRef = inject(TABS_REF_KEY)
const
{
ScrollTopComp
,
handleBackTop
}
=
useScrollTop
(
tabsRef
!
)
defineExpose
({
refresh
:
(
sortLogic
:
number
)
=>
{
refresh
:
(
sortLogic
?
:
number
)
=>
{
console
.
log
(
'sortLogic'
,
sortLogic
)
searchParams
.
value
.
sortLogic
=
sortLogic
refresh
()
...
...
src/views/homePage/homeTab/components/videoList.vue
View file @
4a950630
...
...
@@ -381,6 +381,7 @@ const { list, total, searchParams, loading, goToPage, changePageSize, refresh }
defaultParams
:
{
type
:
ArticleTypeEnum
.
VIDEO
},
defaultCurrent
:
1
,
defaultSize
:
12
,
immediate
:
false
,
},
)
// Tabs 配置
...
...
@@ -397,8 +398,7 @@ const goVideoDetail = (n: number) => {
router
.
push
(
`/videoDetail?id=
${
n
}
`
)
}
defineExpose
({
refresh
:
(
sortLogic
:
number
)
=>
{
searchParams
.
value
.
sortLogic
=
sortLogic
refresh
:
()
=>
{
refresh
()
},
})
...
...
src/views/homePage/homeTab/index.vue
View file @
4a950630
...
...
@@ -2,11 +2,8 @@
<div>
<div
class=
"header h-40px items-center justify-between"
>
<div
class=
"left flex gap-3 flex items-center"
>
<Tabs
v-model=
"activeTab"
:tabs=
"tabs"
@
change=
"(value) => handleTabChange(value as string)"
/>
<Tabs
v-model=
"activeTab"
:tabs=
"tabs"
/>
<!-- 直接在@change里面拿最新的动态组件实例 拿不到 可以在@enter 动画钩子里面拿 -->
<!-- 刷新图标 -->
<el-icon
size=
"15"
...
...
@@ -18,8 +15,11 @@
</div>
<el-divider
style=
"margin: 10px 0 20px 0"
/>
<!-- 主内容区域 -->
<transition
name=
"fade"
mode=
"out-in"
>
<component
ref=
"activeTabComponentRef"
:is=
"activeTabComponent"
/>
<!-- 同一个组件 不同的实例 -->
<transition
name=
"fade"
mode=
"out-in"
@
enter=
"handleEnter"
>
<keep-alive>
<component
ref=
"activeTabComponentRef"
:is=
"activeTabComponent"
:key=
"activeTab"
/>
</keep-alive>
</transition>
</div>
</
template
>
...
...
@@ -40,8 +40,9 @@ const activeTabComponent = computed(() => {
return
tabs
.
find
((
tab
)
=>
tab
.
value
===
activeTab
.
value
)?.
component
})
const
activeTabComponentRef
=
useTemplateRef
<
InstanceType
<
typeof
RecommendList
>>
(
'activeTabComponentRef'
)
const
activeTabComponentRef
=
useTemplateRef
<
InstanceType
<
typeof
RecommendList
>
|
InstanceType
<
typeof
VideoList
>
>
(
'activeTabComponentRef'
)
const
handleRefresh
=
()
=>
{
if
(
activeTab
.
value
===
'推荐'
)
{
...
...
@@ -49,17 +50,17 @@ const handleRefresh = () => {
}
else
if
(
activeTab
.
value
===
'最新'
)
{
activeTabComponentRef
.
value
?.
refresh
?.(
1
)
}
else
if
(
activeTab
.
value
===
'视频'
)
{
activeTabComponentRef
.
value
?.
refresh
?.(
2
)
activeTabComponentRef
.
value
?.
refresh
?.()
}
}
const
handleTabChange
=
(
tab
:
string
)
=>
{
if
(
tab
===
'最新'
)
{
activeTabComponentRef
.
value
?.
refresh
?.(
1
)
}
else
if
(
tab
===
'推荐'
)
{
activeTabComponentRef
.
value
?.
refresh
?.(
0
)
}
const
handleEnter
=
()
=>
{
handleRefresh
()
}
onMounted
(()
=>
{
handleRefresh
()
})
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
src/views/homePage/yaTab/components/columnList.vue
View file @
4a950630
...
...
@@ -17,8 +17,7 @@
{{
item
.
title
}}
</h3>
<div
class=
"flex items-center cursor-pointer"
>
<span
class=
"mr-1 text-14px color-#606266"
>
查看更多
</span>
<el-icon><ArrowRight
/></el-icon>
<span
class=
"mr-1 text-14px color-#606266"
>
查看更多 >>
</span>
</div>
</div>
...
...
@@ -35,10 +34,12 @@
:src=
"i.faceUrl"
class=
"w-full aspect-[5/3] object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div
class=
"absolute top-2 left-2"
>
<el-tag
size=
"small"
class=
"bg-orange-500 text-white border-none"
>
1111111
</el-tag>
<div
v-if=
"i.isRecommend"
class=
"absolute top-0 left-0 w-15 h-7 z-1000 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img
class=
"w-6"
src=
"@/assets/img/culture/recommend.png"
alt=
""
/>
<div
class=
"text-12px text-#000 line-height-12px"
>
推荐
</div>
</div>
</div>
<h3
class=
"text-sm font-medium text-gray-800 mb-2 transition-colors"
>
...
...
src/views/homePage/yaTab/components/interviewList.vue
View file @
4a950630
...
...
@@ -18,9 +18,8 @@
</h3>
<div
class=
"flex items-center cursor-pointer hover:text-[var(--dynamic-color)]"
>
<span
class=
"mr-1 text-14px color-#606266 hover:text-[var(--dynamic-color)]"
>
查看更多
</span
>
查看更多
>>
</span
>
<el-icon><ArrowRight
/></el-icon>
</div>
</div>
...
...
@@ -35,12 +34,14 @@
<div
class=
"relative mb-3 overflow-hidden rounded-lg"
>
<img
:src=
"i.faceUrl"
class=
"w-full
h-32
object-cover group-hover:scale-105 transition-transform duration-300"
class=
"w-full
aspect-[5/3]
object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div
class=
"absolute top-2 left-2"
>
<el-tag
size=
"small"
class=
"bg-orange-500 text-white border-none"
>
1111111
</el-tag>
<div
v-if=
"i.isRecommend"
class=
"absolute top-0 left-0 w-15 h-7 z-1000 bg-#FFF9B9 flex items-center justify-center border-2px border-solid border-#f4f0eb rounded-tl-lg rounded-br-lg"
>
<img
class=
"w-6"
src=
"@/assets/img/culture/recommend.png"
alt=
""
/>
<div
class=
"text-12px text-#000 line-height-12px"
>
推荐
</div>
</div>
</div>
<h3
class=
"text-sm font-medium text-gray-800 mb-2 transition-colors"
>
...
...
src/views/homePage/yaTab/components/practiceList.vue
View file @
4a950630
This diff is collapsed.
Click to expand it.
src/views/publishVideo/index.vue
View file @
4a950630
...
...
@@ -143,7 +143,13 @@
type=
"datetime"
placeholder=
"选择发布时间"
size=
"small"
value-format=
"timestamp"
value-format=
"X"
:disabled-date=
"
(time: Date) =>
{
return time.getTime()
<
Date
.
now
()
-
1000
*
60
*
60
*
24
}
"
style=
"width: 250px"
/>
<el-switch
v-model=
"form.sendType"
...
...
src/views/searchPage/index.vue
0 → 100644
View file @
4a950630
<
template
>
<div
class=
"min-h-screen bg-white"
>
<div
class=
"max-w-1400px mx-auto p-6"
>
<!-- 搜索栏 -->
<div
class=
"mb-8"
>
<div
class=
"relative flex items-center gap-3"
>
<el-input
v-model=
"searchKeyword"
placeholder=
"输入关键词搜索"
size=
"large"
class=
"search-input flex-1"
@
keyup
.
enter=
"handleSearch"
/>
<el-button
type=
"primary"
size=
"large"
class=
"search-btn"
@
click=
"handleSearch"
>
搜索
</el-button>
</div>
</div>
<!-- 分类 Tabs -->
<div
class=
"mb-6 flex gap-3 flex items-center"
>
<Tabs
v-model=
"activeTab"
:tabs=
"tabs"
@
change=
"(value) => handleTabChange(value as string)"
/>
<button
v-for=
"sort in sortOptions"
:key=
"sort.value"
class=
"px-4 py-1.5 rounded-lg text-14px transition-colors"
:class=
"
{
'text-blue-600 bg-blue-50': activeSort === sort.value,
'text-gray-600 hover:text-blue-600': activeSort !== sort.value,
}"
@click="activeSort = sort.value"
>
{{
sort
.
label
}}
</button>
</div>
<!-- 排序方式 -->
<div
class=
"flex items-center justify-between mb-6 py-4 border-b border-gray-200"
>
<div
class=
"flex items-center gap-2"
>
<span
class=
"text-gray-600 text-14px"
>
排序方式:
</span>
<div
class=
"flex gap-2"
>
<button
v-for=
"sort in sortOptions"
:key=
"sort.value"
class=
"px-4 py-1.5 rounded-lg text-14px transition-colors"
:class=
"
{
'text-blue-600 bg-blue-50': activeSort === sort.value,
'text-gray-600 hover:text-blue-600': activeSort !== sort.value,
}"
@click="activeSort = sort.value"
>
{{
sort
.
label
}}
</button>
</div>
</div>
<div
class=
"text-gray-500 text-14px"
>
共找到
<span
class=
"text-blue-600 font-600"
>
{{
totalResults
}}
</span>
条结果
</div>
</div>
<!-- 搜索结果列表 -->
<div
class=
"space-y-4"
>
<div
v-for=
"item in searchResults"
:key=
"item.id"
class=
"flex gap-4 p-4 rounded-lg hover:bg-gray-50 transition-colors cursor-pointer"
>
<!-- 封面图 -->
<div
class=
"flex-shrink-0 w-240px h-135px rounded-lg overflow-hidden bg-gray-100 relative"
>
<img
:src=
"item.cover"
class=
"w-full h-full object-cover"
/>
<div
class=
"absolute bottom-2 right-2 bg-black/70 text-white text-12px px-2 py-0.5 rounded"
>
{{
item
.
duration
}}
</div>
</div>
<!-- 内容信息 -->
<div
class=
"flex-1 flex flex-col justify-between min-w-0"
>
<div>
<!-- 标题 -->
<h3
class=
"text-16px font-500 text-gray-900 mb-2 line-clamp-1"
>
{{
item
.
title
}}
</h3>
<!-- 描述 -->
<p
class=
"text-14px text-gray-600 mb-3 line-clamp-2"
>
{{
item
.
description
}}
</p>
</div>
<!-- 底部信息 -->
<div
class=
"flex items-center gap-4 text-13px text-gray-500"
>
<span>
{{
item
.
author
}}
</span>
<span>
{{
item
.
views
}}
</span>
<span>
{{
item
.
time
}}
</span>
</div>
</div>
<!-- 右侧视频标签 -->
<div
class=
"flex-shrink-0 self-end"
>
<span
class=
"text-blue-600 text-13px"
>
视频
</span>
</div>
</div>
</div>
<!-- 分页 -->
<div
class=
"mt-8 flex justify-center"
>
<el-pagination
v-model:current-page=
"currentPage"
v-model:page-size=
"pageSize"
:total=
"totalResults"
:page-sizes=
"[10, 20, 30, 50]"
layout=
"total, sizes, prev, pager, next, jumper"
/>
</div>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
'vue'
import
Tabs
from
'@/components/common/Tabs'
interface
SearchResult
{
id
:
number
title
:
string
description
:
string
cover
:
string
duration
:
string
author
:
string
views
:
string
time
:
string
}
const
searchKeyword
=
ref
(
'wayward'
)
const
tabs
=
[
{
label
:
'综合'
,
value
:
'综合'
,
count
:
189
},
{
label
:
'视频'
,
value
:
'视频'
,
count
:
89
},
{
label
:
'帖子'
,
value
:
'帖子'
,
count
:
0
},
{
label
:
'实践'
,
value
:
'实践'
,
count
:
0
},
{
label
:
'专栏'
,
value
:
'专栏'
,
count
:
0
},
{
label
:
'专访'
,
value
:
'专访'
,
count
:
51
},
{
label
:
'问题'
,
value
:
'问题'
,
count
:
0
},
]
const
activeTab
=
ref
(
'综合'
)
const
sortOptions
=
ref
([
{
label
:
'综合排序'
,
value
:
'default'
},
{
label
:
'最多播放'
,
value
:
'views'
},
{
label
:
'最新发布'
,
value
:
'time'
},
{
label
:
'最多收藏'
,
value
:
'favorite'
},
])
const
activeSort
=
ref
(
'default'
)
const
totalResults
=
ref
(
189
)
const
currentPage
=
ref
(
1
)
const
pageSize
=
ref
(
20
)
const
searchResults
=
ref
<
SearchResult
[]
>
([
{
id
:
1
,
title
:
'wayward:已经20小时了!第3次挑战灭火了'
,
description
:
'wayward这次挑战能否成功?经历了前两次失败后,这次能否成功灭火?让我们拭目以待...'
,
cover
:
'https://picsum.photos/400/225?random=1'
,
duration
:
'20:45'
,
author
:
'waywardzz'
,
views
:
'1.2万'
,
time
:
'2天前'
,
},
{
id
:
2
,
title
:
'wayward:只是喝成这样还怎么玩?长江水果实太快了'
,
description
:
'这期节目真的太搞笑了,wayward的状态实在是...'
,
cover
:
'https://picsum.photos/400/225?random=2'
,
duration
:
'15:30'
,
author
:
'waywardzz'
,
views
:
'8956'
,
time
:
'3天前'
,
},
{
id
:
3
,
title
:
'wayward生存挑战20小时记录'
,
description
:
'完整记录wayward的20小时生存挑战过程,从开始到结束的所有精彩瞬间...'
,
cover
:
'https://picsum.photos/400/225?random=3'
,
duration
:
'1:20:15'
,
author
:
'waywardFan'
,
views
:
'5.6万'
,
time
:
'1周前'
,
},
])
const
handleSearch
=
()
=>
{
console
.
log
(
'搜索关键词:'
,
searchKeyword
.
value
)
}
const
handleTabChange
=
(
value
:
string
)
=>
{
console
.
log
(
'切换分类:'
,
value
)
activeTab
.
value
=
value
}
</
script
>
<
style
scoped
>
:deep
(
.search-input
.el-input__wrapper
)
{
border-radius
:
0.5rem
;
border
:
1px
solid
#e5e7eb
;
}
:deep
(
.search-btn
)
{
background
:
#3b82f6
;
border
:
none
;
border-radius
:
0.5rem
;
padding
:
0
2rem
;
}
.line-clamp-1
{
display
:
-webkit-box
;
-webkit-line-clamp
:
1
;
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
}
.line-clamp-2
{
display
:
-webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
}
</
style
>
vite.config.ts
View file @
4a950630
...
...
@@ -50,8 +50,8 @@ export default defineConfig({
port
:
3000
,
proxy
:
{
'/api1'
:
{
//
target: 'http://192.168.2.168:8089', // 立鹏本地
target
:
'http://192.168.2.55:8089'
,
// 首拥本地
target
:
'http://192.168.2.168:8089'
,
// 立鹏本地
//
target: 'http://192.168.2.55:8089', // 首拥本地
changeOrigin
:
true
,
rewrite
:
(
path
)
=>
{
return
path
.
replace
(
/^
\/
api1/
,
''
)
...
...
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