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
d66ac723
You need to sign in or sign up before continuing.
Commit
d66ac723
authored
Aug 31, 2026
by
王立鹏
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/23684-【YAYA文化岛】改动汇总' into 'master'
Feature/23684 【yaya文化岛】改动汇总 See merge request
!35
parents
a24b3b2b
e0f5e0ae
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
422 additions
and
135 deletions
+422
-135
index.html
index.html
+1
-1
index.ts
src/api/article/index.ts
+25
-0
types.ts
src/api/article/types.ts
+18
-0
index.ts
src/api/backend/activity/index.ts
+3
-2
types.ts
src/api/backend/activity/types.ts
+12
-2
types.ts
src/api/practice/types.ts
+1
-0
lucky-wheel-happy-adventure.mp3
src/assets/audio/lucky-wheel-happy-adventure.mp3
+0
-0
webicon.png
src/assets/img/webicon.png
+0
-0
index.vue
src/components/common/ArticleContent/index.vue
+69
-6
LuckyWheel.vue
...ents/common/LuckyWheelContainer/components/LuckyWheel.vue
+42
-9
index.vue
src/components/common/LuckyWheelContainer/index.vue
+32
-26
index.vue
src/components/common/PublishBox/index.vue
+22
-1
exchangeGoodsRecordDilaog.vue
src/views/auction/components/exchangeGoodsRecordDilaog.vue
+2
-2
exchangeYabiRecordDilaog.vue
src/views/auction/components/exchangeYabiRecordDilaog.vue
+1
-1
index.vue
src/views/auction/index.vue
+8
-1
index.vue
src/views/backend/contentsMenu/videoManage/index.vue
+21
-1
index.vue
src/views/backend/index.vue
+13
-13
index.vue
src/views/backend/settingsMenu/auctionManage/index.vue
+79
-16
lotteryConfigDialog.vue
...enu/dailyLotteryManage/components/lotteryConfigDialog.vue
+24
-5
index.vue
src/views/backend/settingsMenu/goodsManage/index.vue
+4
-4
index.vue
src/views/columnSearchList/index.vue
+1
-1
exchangeContent.tsx
src/views/pointsStore/components/exchangeContent.tsx
+16
-3
exchangeGoodsRecordDilaog.vue
...iews/pointsStore/components/exchangeGoodsRecordDilaog.vue
+2
-2
exchangeYabiRecordDilaog.vue
...views/pointsStore/components/exchangeYabiRecordDilaog.vue
+1
-1
index.vue
src/views/pointsStore/index.vue
+23
-36
index.vue
src/views/publishLongArticle/index.vue
+1
-1
index.vue
src/views/videoSearchList/index.vue
+1
-1
No files found.
index.html
View file @
d66ac723
...
...
@@ -2,7 +2,7 @@
<html
lang=
""
>
<head>
<meta
charset=
"UTF-8"
/>
<link
rel=
"icon"
href=
"/webicon.png"
/>
<link
rel=
"icon"
href=
"/
src/assets/img/
webicon.png"
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
/>
<title>
企业文化平台
</title>
</head>
...
...
src/api/article/index.ts
View file @
d66ac723
...
...
@@ -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 @
d66ac723
...
...
@@ -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
}
/**
...
...
@@ -413,6 +415,7 @@ export interface SearchMoreColumnItemDto {
type
:
ArticleTypeEnum
.
COLUMN
videoDuration
:
string
viewCount
:
number
publishTime
:
number
}
/**
...
...
@@ -502,3 +505,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/api/backend/activity/index.ts
View file @
d66ac723
...
...
@@ -2,6 +2,7 @@ import service from '@/utils/request/index'
import
type
{
BackendAuctionListSearchParams
,
BackendAuctionListItemDto
,
BackendDeleteAuctionDto
,
BackendAddOrUpdateAuctionItemDto
,
BackendAuctionRecordItemDto
,
BackendLotteryPrizeListSearchParams
,
...
...
@@ -44,11 +45,11 @@ export const addOrUpdateAuctionItem = (data: BackendAddOrUpdateAuctionItemDto) =
/**
* 删除竞拍物品数据
*/
export
const
deleteAuction
=
(
idList
:
number
[]
)
=>
{
export
const
deleteAuction
=
(
data
:
BackendDeleteAuctionDto
)
=>
{
return
service
.
request
({
url
:
'api/cultureAuctionItems/deleteAuction'
,
method
:
'POST'
,
data
:
{
idList
}
,
data
,
})
}
...
...
src/api/backend/activity/types.ts
View file @
d66ac723
...
...
@@ -36,8 +36,14 @@ export interface BackendAuctionListItemDto extends PageSearchParams {
remainingTime
:
string
}
export
interface
BackendDeleteAuctionDto
{
idList
:
number
[]
confirmDelete
:
boolean
}
export
interface
BackendAddOrUpdateAuctionItemDto
{
id
?:
number
status
?:
AuctionStatusEnum
name
:
string
quantity
:
number
specification
:
string
...
...
@@ -83,8 +89,10 @@ export interface BackendAddOrUpdateLotteryConfigDto {
startDate
:
string
endDate
:
string
autoCloseWeekend
:
BooleanFlag
registrationStartHour
:
string
registrationEndHour
:
string
registrationStartHour
:
number
registrationStartMinute
:
number
registrationEndHour
:
number
registrationEndMinute
:
number
registrationFee
:
number
}
...
...
@@ -98,8 +106,10 @@ export type BackendLotteryConfigDto = {
prizesImg
:
string
prizesName
:
string
registrationEndHour
:
number
registrationEndMinute
:
number
registrationFee
:
number
registrationStartHour
:
number
registrationStartMinute
:
number
startDate
:
number
status
:
BooleanFlag
updatedAt
:
number
...
...
src/api/practice/types.ts
View file @
d66ac723
...
...
@@ -15,6 +15,7 @@ export interface AddOrUpdatePracticeDto {
tagList
:
{
tagId
:
number
;
sort
:
number
}[]
sendType
:
SendTypeEnum
sendTime
:
string
deptId
?:
string
type
?:
ArticleTypeEnum
}
...
...
src/assets/audio/lucky-wheel-happy-adventure.mp3
0 → 100644
View file @
d66ac723
File added
public
/webicon.png
→
src/assets/img
/webicon.png
View file @
d66ac723
File moved
src/components/common/ArticleContent/index.vue
View file @
d66ac723
...
...
@@ -232,13 +232,48 @@
</div>
<!-- 标签 -->
<div
class=
"flex flex-wrap gap-2 mt-6"
>
<
span
v-for=
"
item
in articleDetail?.tagNameList"
<
el-tooltip
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"
:content=
"canLoadRelatedColumns ? '点击查看相关推荐专栏' : ''"
:disabled=
"!canLoadRelatedColumns"
placement=
"top"
:show-after=
"200"
>
#{{ item }}
</span>
<button
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 }}
</button>
</el-tooltip>
</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 +293,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 +325,34 @@ 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
.
slice
(
0
,
3
)
}
catch
{
relatedColumnList
.
value
=
[]
}
finally
{
relatedColumnLoading
.
value
=
false
}
}
// 是否是作者
const
isAuthor
=
computed
(()
=>
{
return
articleDetail
.
createUserId
===
userInfo
.
value
.
userId
...
...
src/components/common/LuckyWheelContainer/components/LuckyWheel.vue
View file @
d66ac723
...
...
@@ -30,6 +30,7 @@
<
script
lang=
"ts"
setup
>
import
{
LuckyWheel
}
from
'@lucky-canvas/vue'
import
ringTexture
from
'@/assets/img/lucky-wheel-outer-ring.svg'
import
spinMusic
from
'@/assets/audio/lucky-wheel-happy-adventure.mp3'
import
type
{
WheelPrizeItemDto
,
LuckWheelResultDto
,
WheelConfigDto
}
from
'@/api'
import
{
participateLuckyWheel
,
getWheelPrizeList
}
from
'@/api'
...
...
@@ -56,8 +57,8 @@ const myLucky = ref<InstanceType<typeof LuckyWheel>>()
const
defaultConfig
=
{
offsetDegree
:
0
,
speed
:
20
,
accelerationTime
:
25
00
,
decelerationTime
:
25
00
,
accelerationTime
:
10
00
,
decelerationTime
:
10
00
,
}
const
defaultStyle
=
{
...
...
@@ -124,18 +125,42 @@ const buttons = [
const
isSpinning
=
ref
(
false
)
let
resultPrize
:
null
|
LuckWheelResultDto
=
null
let
spinAudio
:
HTMLAudioElement
|
null
=
null
const
startSpinMusic
=
()
=>
{
stopSpinMusic
()
spinAudio
||=
new
Audio
(
spinMusic
)
spinAudio
.
loop
=
true
spinAudio
.
volume
=
0.35
spinAudio
.
play
().
catch
(()
=>
{})
}
const
stopSpinMusic
=
()
=>
{
if
(
!
spinAudio
)
return
spinAudio
.
pause
()
spinAudio
.
currentTime
=
0
}
const
startCallback
=
async
()
=>
{
if
(
isSpinning
.
value
)
return
isSpinning
.
value
=
true
startSpinMusic
()
myLucky
.
value
?.
play
()
setTimeout
(
async
()
=>
{
const
{
data
}
=
await
participateLuckyWheel
()
const
idx
=
computedPrizes
.
value
.
findIndex
((
item
)
=>
item
.
id
===
data
.
prizeId
)
myLucky
.
value
?.
stop
(
idx
)
yabiStore
.
fetchYaBiData
()
resultPrize
=
data
},
1000
)
try
{
const
{
data
}
=
await
participateLuckyWheel
()
const
idx
=
computedPrizes
.
value
.
findIndex
((
item
)
=>
item
.
id
===
data
.
prizeId
)
myLucky
.
value
?.
stop
(
idx
)
yabiStore
.
fetchYaBiData
()
resultPrize
=
data
}
catch
(
error
)
{
console
.
error
(
error
)
stopSpinMusic
()
isSpinning
.
value
=
false
}
},
600
)
}
// 获取最新的奖品列表 对比 是否更新了
...
...
@@ -185,7 +210,7 @@ const endCallback = () => {
setTimeout(() => {
isSpinning.value = false
emit('handlePrizeResult', resultPrize as LuckWheelResultDto)
},
50
0)
},
28
0)
}
const initWheelPrizeList = async () => {
...
...
@@ -195,6 +220,14 @@ const initWheelPrizeList = async () => {
onMounted(() => {
initWheelPrizeList()
})
onBeforeUnmount(() => {
stopSpinMusic()
})
defineExpose({
stopSpinMusic,
})
</
script
>
<
style
scoped
>
...
...
src/components/common/LuckyWheelContainer/index.vue
View file @
d66ac723
<
template
>
<Comp
:wheelConfig=
"wheelConfig"
@
handle-prize-result=
"handlePrizeResult"
/>
<Comp
ref=
"luckyWheelRef"
:wheelConfig=
"wheelConfig"
@
handle-prize-result=
"handlePrizeResult"
/>
<Teleport
to=
"body"
>
<Transition
name=
"result"
>
<div
...
...
@@ -84,7 +84,7 @@
<p
class=
"blessing-caption-subtitle"
>
抽一支好运电子签,把今天过得亮一点
</p>
</div>
<el-button
class=
"mt-8"
type=
"primary"
@
click=
"
showResult = false
"
>
知道了
</el-button>
<el-button
class=
"mt-8"
type=
"primary"
@
click=
"
closeResult
"
>
知道了
</el-button>
</
template
>
<
template
v-else
>
...
...
@@ -92,7 +92,7 @@
<div
class=
"mt-6 text-white text-3xl font-bold"
>
恭喜获得
{{
currentPrize
?.
prizeName
}}
</div>
<el-button
class=
"mt-8"
type=
"primary"
@
click=
"
showResult = false
"
>
知道了
</el-button>
<el-button
class=
"mt-8"
type=
"primary"
@
click=
"
closeResult
"
>
知道了
</el-button>
</
template
>
</div>
</Transition>
...
...
@@ -112,6 +112,7 @@ const { wheelConfig } = defineProps<{
const
showResult
=
ref
(
false
)
const
currentPrize
=
ref
<
LuckWheelResultDto
|
null
>
(
null
)
const
luckyWheelRef
=
ref
<
InstanceType
<
typeof
Comp
>>
()
const
blessingWrapRef
=
ref
<
HTMLElement
|
null
>
(
null
)
const
blessingGlowRef
=
ref
<
HTMLElement
|
null
>
(
null
)
...
...
@@ -305,10 +306,10 @@ const playBlessingAnimation = () => {
})
blessingTimeline
.
to
(
scene
,
{
opacity
:
1
,
y
:
0
,
duration
:
0.
4
5
})
.
to
(
glow
,
{
opacity
:
0.95
,
scale
:
1
,
duration
:
0.
7
,
ease
:
'sine.out'
},
'<'
)
.
to
(
slot
,
{
opacity
:
1
,
scaleX
:
1
,
duration
:
0.
52
},
'-=0.3
'
)
.
to
(
fan
,
{
opacity
:
1
,
y
:
0
,
duration
:
0.4
},
'<'
)
.
to
(
scene
,
{
opacity
:
1
,
y
:
0
,
duration
:
0.
3
5
})
.
to
(
glow
,
{
opacity
:
0.95
,
scale
:
1
,
duration
:
0.
55
,
ease
:
'sine.out'
},
'<'
)
.
to
(
slot
,
{
opacity
:
1
,
scaleX
:
1
,
duration
:
0.
42
},
'-=0.26
'
)
.
to
(
fan
,
{
opacity
:
1
,
y
:
0
,
duration
:
0.
3
4
},
'<'
)
.
to
(
fanItems
,
{
...
...
@@ -316,10 +317,10 @@ const playBlessingAnimation = () => {
y
:
(
_index
,
target
)
=>
Number
(
target
.
getAttribute
(
'data-y'
)
||
0
),
rotate
:
(
_index
,
target
)
=>
Number
(
target
.
getAttribute
(
'data-angle'
)
||
0
),
scale
:
(
_index
,
target
)
=>
Number
(
target
.
getAttribute
(
'data-scale'
)
||
1
),
duration
:
0.
9
,
duration
:
0.
7
,
ease
:
'back.out(1.08)'
,
stagger
:
{
each
:
0.0
55
,
each
:
0.0
42
,
from
:
'center'
,
},
},
...
...
@@ -329,16 +330,16 @@ const playBlessingAnimation = () => {
fanItems
,
{
x
:
(
_index
,
target
)
=>
Number
(
target
.
getAttribute
(
'data-x'
)
||
0
)
*
0.1
,
duration
:
0.
32
,
duration
:
0.
26
,
ease
:
'power1.inOut'
,
stagger
:
{
each
:
0.0
2
,
each
:
0.0
16
,
from
:
'edges'
,
},
yoyo
:
true
,
repeat
:
1
,
},
'+=0.
26
'
,
'+=0.
18
'
,
)
.
to
(
blessingTagStageRef
.
value
,
...
...
@@ -346,10 +347,10 @@ const playBlessingAnimation = () => {
opacity
:
1
,
y
:
0
,
filter
:
'blur(0px)'
,
duration
:
0.
48
,
duration
:
0.
36
,
ease
:
'power2.out'
,
},
'+=0.0
2
'
,
'+=0.0
1
'
,
)
.
to
(
tag
,
...
...
@@ -358,7 +359,7 @@ const playBlessingAnimation = () => {
opacity
:
0.5
,
scale
:
0.97
,
filter
:
'blur(6px)'
,
duration
:
0.
42
,
duration
:
0.
34
,
ease
:
'power2.out'
,
},
'<'
,
...
...
@@ -370,10 +371,10 @@ const playBlessingAnimation = () => {
opacity
:
1
,
scale
:
1.01
,
filter
:
'blur(1px)'
,
duration
:
1.08
,
duration
:
0.82
,
ease
:
'power3.out'
,
},
'+=0.
1
'
,
'+=0.
08
'
,
)
.
to
(
tag
,
...
...
@@ -382,10 +383,10 @@ const playBlessingAnimation = () => {
rotation
:
-
1.4
,
scale
:
1.015
,
filter
:
'blur(0px)'
,
duration
:
0.
3
,
duration
:
0.
24
,
ease
:
'power2.out'
,
},
'-=0.1
8
'
,
'-=0.1
4
'
,
)
.
to
(
tag
,
...
...
@@ -394,19 +395,19 @@ const playBlessingAnimation = () => {
rotation
:
0.4
,
scale
:
1
,
filter
:
'blur(0px)'
,
duration
:
0.
32
,
duration
:
0.
26
,
ease
:
'back.out(1.5)'
,
},
'+=0.0
2
'
,
'+=0.0
1
'
,
)
.
to
(
tagTop
,
{
opacity
:
1
,
duration
:
0.
22
},
'<'
)
.
to
(
tagTop
,
{
opacity
:
1
,
duration
:
0.
18
},
'<'
)
.
to
(
chars
,
{
opacity
:
1
,
y
:
0
,
duration
:
0.
34
,
stagger
:
0.05
,
duration
:
0.
28
,
stagger
:
0.0
3
5
,
},
'-=0.08'
,
)
...
...
@@ -415,7 +416,7 @@ const playBlessingAnimation = () => {
{
opacity
:
1
,
y
:
0
,
duration
:
0.2
8
,
duration
:
0.2
2
,
},
'-=0.12'
,
)
...
...
@@ -424,7 +425,7 @@ const playBlessingAnimation = () => {
{
opacity
:
1
,
y
:
0
,
duration
:
0.
42
,
duration
:
0.
34
,
},
'-=0.02'
,
)
...
...
@@ -461,6 +462,11 @@ const handlePrizeResult = (prize: LuckWheelResultDto) => {
currentPrize
.
value
=
prize
showResult
.
value
=
true
}
const
closeResult
=
()
=>
{
showResult
.
value
=
false
luckyWheelRef
.
value
?.
stopSpinMusic
()
}
</
script
>
<
style
>
...
...
src/components/common/PublishBox/index.vue
View file @
d66ac723
...
...
@@ -62,6 +62,21 @@
:height=
"100"
/>
</div>
<div
v-if=
"userInfo.isOfficialAccount && type === ArticleTypeEnum.PRACTICE"
class=
"mb-3"
>
<el-select
v-model=
"form.deptId"
placeholder=
"请选择所属一级部门"
clearable
class=
"w-full"
>
<el-option
v-for=
"item in firstDepListOptions"
:key=
"item.id"
:value=
"item.id"
:label=
"item.name"
/>
</el-select>
</div>
<!-- 标签内容 -->
<div
class=
"mb-2"
>
<!-- 选择的标签内容 -->
...
...
@@ -148,7 +163,12 @@ import { useUserStore } from '@/stores'
import
{
storeToRefs
}
from
'pinia'
import
SelectTagsDialog
from
'./components/selectTagsDialog.vue'
import
{
useResetData
,
useUploadImg
}
from
'@/hooks'
import
{
ArticleTypeEnum
,
ReleaseStatusTypeEnum
,
SendTypeEnum
}
from
'@/constants'
import
{
ArticleTypeEnum
,
firstDepListOptions
,
ReleaseStatusTypeEnum
,
SendTypeEnum
,
}
from
'@/constants'
import
{
useTagsStore
}
from
'@/stores'
import
{
addOrUpdatePractice
,
addOrUpdateArticle
}
from
'@/api'
import
type
{
AddOrUpdatePracticeDto
}
from
'@/api'
...
...
@@ -238,6 +258,7 @@ const [form, , forReset] = useResetData({
tagList
:
[],
sendType
:
SendTypeEnum
.
IMMEDIATE
,
sendTime
:
''
,
deptId
:
''
,
})
const
{
imgList
,
handleFileChange
,
handleDeleteImg
,
uploadPercent
}
=
useUploadImg
(
...
...
src/views/auction/components/exchangeGoodsRecordDilaog.vue
View file @
d66ac723
...
...
@@ -13,7 +13,7 @@
<div
class=
"w-750px flex items-center gap-3"
>
<el-select
v-model=
"searchParams.itemType"
placeholder=
"选择商品类型"
clearable
>
<el-option
label=
"亚声实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
<el-option
label=
"虚拟
装饰
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
<el-option
label=
"虚拟
商品
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
</el-select>
<el-date-picker
...
...
@@ -38,7 +38,7 @@
<el-table-column
prop=
"itemType"
label=
"商品类型"
width=
"100"
align=
"center"
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
?
'亚声实物'
:
'虚拟
装饰
'
}}
{{
scope
.
row
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
?
'亚声实物'
:
'虚拟
商品
'
}}
</
template
>
</el-table-column>
...
...
src/views/auction/components/exchangeYabiRecordDilaog.vue
View file @
d66ac723
...
...
@@ -13,7 +13,7 @@
<div
class=
"w-750px flex items-center gap-3"
>
<!--
<el-select
v-model=
"searchParams.type"
placeholder=
"选择商品类型"
clearable
>
<el-option
label=
"亚声实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
<el-option
label=
"虚拟
装饰
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
<el-option
label=
"虚拟
商品
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
</el-select>
-->
<el-date-picker
...
...
src/views/auction/index.vue
View file @
d66ac723
...
...
@@ -175,10 +175,17 @@ const onBid = async (item: AuctionItemDto) => {
}
else
{
if
(
val
.
value
>
yabiData
.
value
.
currentValue
)
return
push
.
error
(
'您的YA币余额不足'
)
if
(
val
.
value
<
data
.
minIncrement
+
(
data
.
currentPrice
||
data
.
startingPrice
))
// 如果还没有出价 只需要出价大于等于起拍价
if
(
data
.
currentPrice
===
0
)
{
if
(
val
.
value
<
data
.
startingPrice
)
return
push
.
error
(
`出价必须大于等于起拍价: 至少【
${
data
.
startingPrice
}
】YA币`
,
)
}
else
{
if
(
val
.
value
<
data
.
minIncrement
+
(
data
.
currentPrice
||
data
.
startingPrice
))
return
push
.
error
(
`出价必须大于等于前最高出价+最低加价幅度: 至少【
${
data
.
minIncrement
+
(
data
.
currentPrice
||
data
.
startingPrice
)}
】YA币`
,
)
}
instance
.
confirmButtonLoading
=
true
instance
.
confirmButtonText
=
'Loading...'
...
...
src/views/backend/contentsMenu/videoManage/index.vue
View file @
d66ac723
...
...
@@ -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"
>
...
...
src/views/backend/index.vue
View file @
d66ac723
<
script
lang=
"tsx"
>
import
{
KeepAlive
,
Transition
}
from
'vue'
import
type
{
Component
as
VueComponent
}
from
'vue'
import
webIconUrl
from
'@/assets/img/webicon.png'
export
default
defineComponent
(()
=>
{
interface
MenuItem
{
path
:
string
...
...
@@ -23,7 +24,6 @@ export default defineComponent(() => {
// { path: '/backend/videoManage', title: '视频管理' },
{
path
:
'/backend/caseManage'
,
title
:
'YAYA案例库管理'
},
// { path: '/backend/goodsManage', title: '积分商城——商品配置' },
{
path
:
'/backend/goodsDistribution'
,
title
:
'商品分发'
},
// 内容管理
{
path
:
'/backend/contentsMenu'
,
...
...
@@ -35,7 +35,16 @@ export default defineComponent(() => {
{
path
:
'/backend/contentsMenu/questionManage'
,
title
:
'问吧管理'
},
],
},
// 栏目管理
{
path
:
'/backend/columnsMenu'
,
title
:
'栏目管理'
,
children
:
[
{
path
:
'/backend/columnsMenu/columnManage'
,
title
:
'专栏——栏目管理'
},
{
path
:
'/backend/columnsMenu/interviewManage'
,
title
:
'专访——栏目管理'
},
{
path
:
'/backend/columnsMenu/videoManage'
,
title
:
'视频——栏目管理'
},
],
},
// 配置管理
{
path
:
'/backend/settingsMenu'
,
...
...
@@ -47,16 +56,7 @@ export default defineComponent(() => {
{
path
:
'/backend/settingsMenu/luckyWheelManage'
,
title
:
'转盘抽奖配置'
},
],
},
// 栏目管理
{
path
:
'/backend/columnsMenu'
,
title
:
'栏目管理'
,
children
:
[
{
path
:
'/backend/columnsMenu/columnManage'
,
title
:
'专栏——栏目管理'
},
{
path
:
'/backend/columnsMenu/interviewManage'
,
title
:
'专访——栏目管理'
},
{
path
:
'/backend/columnsMenu/videoManage'
,
title
:
'视频——栏目管理'
},
],
},
{
path
:
'/backend/goodsDistribution'
,
title
:
'商品分发'
},
]
const
activeMenu
=
computed
(()
=>
route
.
path
)
...
...
@@ -111,7 +111,7 @@ export default defineComponent(() => {
<
div
class
=
"backend-layout"
>
<
aside
class
=
"backend-sidebar"
>
<
div
class
=
"sidebar-header"
>
<
img
src
=
"/webicon.png"
alt
=
"SOUNDASIA"
class
=
"logo"
/>
<
img
src
=
{
webIconUrl
}
alt
=
"SOUNDASIA"
class
=
"logo"
/>
<
span
class
=
"header-title"
>
企业文化后台管理
<
/span
>
<
/div
>
...
...
src/views/backend/settingsMenu/auctionManage/index.vue
View file @
d66ac723
...
...
@@ -88,7 +88,7 @@
{{
// 未展示的时候不展示竞拍状态
row
.
isDisplay
===
0
?
''
?
'
未展示在前台时不展示竞拍状态
'
:
auctionStatusListOptions
.
find
((
item
)
=>
item
.
value
===
row
.
status
)?.
label
}}
</
template
>
...
...
@@ -195,6 +195,17 @@
inactive-text=
"否"
/>
</el-form-item>
<el-form-item
v-if=
"form.id"
label=
"竞拍状态"
prop=
"status"
>
<el-select
v-model=
"form.status"
placeholder=
"请选择竞拍状态"
class=
"w-60%!"
>
<el-option
v-for=
"item in editAuctionStatusOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
:disabled=
"item.disabled"
/>
</el-select>
</el-form-item>
</el-form>
</el-scrollbar>
<
template
#
footer
>
...
...
@@ -221,7 +232,7 @@ import {
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendAuctionListItemDto
,
BackendAddOrUpdateAuctionItemDto
}
from
'@/api/backend'
import
{
auctionStatusListOptions
}
from
'@/constants'
import
{
AuctionStatusEnum
,
auctionStatusListOptions
}
from
'@/constants'
import
UploadFile
from
'@/components/common/UploadFile/index.vue'
import
AuctionRecordDialog
from
'./components/auctionRecordDialog.vue'
import
dayjs
from
'dayjs'
...
...
@@ -253,19 +264,45 @@ const [form, resetForm] = useResetData<BackendAddOrUpdateAuctionItemDto>({
isDisplay
:
0
,
startTime
:
''
,
endTime
:
''
,
status
:
undefined
,
})
// 可编辑的 竞拍状态 只可以选择 「竞拍成功 / 已流拍」
const
editAuctionStatusOptions
=
computed
(()
=>
{
const
options
=
auctionStatusListOptions
.
filter
((
item
)
=>
[
AuctionStatusEnum
.
AUCTION_SUCCESS
,
AuctionStatusEnum
.
AUCTION_FAILED
].
includes
(
item
.
value
),
)
.
map
((
item
)
=>
({
...
item
,
disabled
:
false
,
}))
const
hasCurrentStatus
=
options
.
some
((
item
)
=>
item
.
value
===
form
.
value
.
status
)
if
(
form
.
value
.
status
!==
undefined
&&
!
hasCurrentStatus
)
{
const
currentStatus
=
auctionStatusListOptions
.
find
((
item
)
=>
item
.
value
===
form
.
value
.
status
)
options
.
unshift
({
label
:
currentStatus
?.
label
||
`未知状态(
${
form
.
value
.
status
}
)`
,
value
:
form
.
value
.
status
,
disabled
:
true
,
})
}
return
options
})
// 表单验证规则
const
formRules
:
FormRules
=
{
name
:
[{
required
:
true
,
message
:
'请输入名称'
,
trigger
:
'blur'
}],
description
:
[{
required
:
true
,
message
:
'请输入介绍内容'
,
trigger
:
'blur'
}],
quantity
:
[{
required
:
true
,
message
:
'请输入数量'
,
trigger
:
'blur'
}],
specification
:
[{
required
:
true
,
message
:
'请输入规格'
,
trigger
:
'blur'
}],
//
specification: [{ required: true, message: '请输入规格', trigger: 'blur' }],
startingPrice
:
[{
required
:
true
,
message
:
'请输入起拍价'
,
trigger
:
'blur'
}],
minIncrement
:
[{
required
:
true
,
message
:
'请输入最低加价幅度'
,
trigger
:
'blur'
}],
bidLimit
:
[{
required
:
true
,
message
:
'请输入竞拍次数上限'
,
trigger
:
'blur'
}],
startTime
:
[{
required
:
true
,
message
:
'请选择竞拍时间'
,
trigger
:
'change'
}],
isDisplay
:
[{
required
:
true
,
message
:
'请选择是否展示在前台'
,
trigger
:
'blur'
}],
imageUrl
:
[{
required
:
true
,
message
:
'请上传图片'
,
trigger
:
'change'
}],
status
:
[{
required
:
true
,
message
:
'请选择竞拍状态'
,
trigger
:
'change'
}],
}
const
dateRange
=
computed
({
get
()
{
...
...
@@ -304,21 +341,18 @@ const handleEdit = (row: BackendAddOrUpdateAuctionItemDto) => {
// 删除
const
handleDelete
=
async
(
row
:
BackendAuctionListItemDto
)
=>
{
const
confirmDelete
=
row
.
currentPrice
>
0
await
confirm
({
title
:
'提示'
,
message
:
`确定要删除竞拍物品"
${
row
.
name
}
"吗?`
,
message
:
confirmDelete
?
'该竞拍已有人出价,是否确定删除?删除后无法恢复,并会同步删除竞拍者的记录'
:
`确定要删除竞拍物品"
${
row
.
name
}
"吗?`
,
type
:
'danger'
,
})
try
{
await
deleteAuction
([
row
.
id
])
refresh
()
push
.
success
(
'删除成功'
)
refresh
()
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
push
.
error
(
'删除失败'
)
}
}
await
deleteAuction
({
idList
:
[
row
.
id
],
confirmDelete
})
refresh
()
push
.
success
(
'删除成功'
)
}
// 提交表单
...
...
@@ -384,13 +418,42 @@ const handleBatchShow = async () => {
}
const
handleBatchDelete
=
async
()
=>
{
const
bidRows
=
selectedRows
.
value
.
filter
((
item
)
=>
item
.
currentPrice
>
0
)
const
unbidRows
=
selectedRows
.
value
.
filter
((
item
)
=>
item
.
currentPrice
===
0
)
const
formatNames
=
(
rows
:
BackendAuctionListItemDto
[])
=>
rows
.
map
((
item
)
=>
`【
${
item
.
name
}
】`
).
join
(
''
)
let
message
=
`确定要删除竞拍物品
${
formatNames
(
unbidRows
)}
吗?`
if
(
bidRows
.
length
&&
unbidRows
.
length
)
{
message
=
`其中
${
formatNames
(
bidRows
)}
这些竞拍已有人出价,是否确定删除?删除后无法恢复,并会同步删除竞拍者的记录,其余
${
formatNames
(
unbidRows
)}
未出价会正常删除,确定删除吗?`
}
else
if
(
bidRows
.
length
)
{
message
=
`
${
formatNames
(
bidRows
)}
这些竞拍已有人出价,是否确定删除?删除后无法恢复,并会同步删除竞拍者的记录,确定删除吗?`
}
await
confirm
({
title
:
'提示'
,
message
:
'确定要删除这些竞拍物品吗?'
,
message
,
type
:
'danger'
,
})
await
deleteAuction
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
if
(
unbidRows
.
length
&&
bidRows
.
length
)
{
await
Promise
.
all
([
deleteAuction
({
idList
:
unbidRows
.
map
((
item
)
=>
item
.
id
),
confirmDelete
:
false
,
}),
deleteAuction
({
idList
:
bidRows
.
map
((
item
)
=>
item
.
id
),
confirmDelete
:
true
,
}),
])
}
else
{
const
rows
=
bidRows
.
length
?
bidRows
:
unbidRows
await
deleteAuction
({
idList
:
rows
.
map
((
item
)
=>
item
.
id
),
confirmDelete
:
bidRows
.
length
>
0
,
})
}
refresh
()
push
.
success
(
'删除成功'
)
}
...
...
src/views/backend/settingsMenu/dailyLotteryManage/components/lotteryConfigDialog.vue
View file @
d66ac723
...
...
@@ -38,8 +38,8 @@
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
is-range
format=
"HH:
00
"
value-format=
"H"
format=
"HH:
mm
"
value-format=
"H
H:mm
"
/>
</el-form-item>
<!-- 报名费用 -->
...
...
@@ -93,6 +93,18 @@ const visible = ref(false)
const
formRef
=
ref
<
FormInstance
>
()
const
loading
=
ref
(
false
)
const
formatRegistrationTime
=
(
hour
:
number
,
minute
=
0
)
=>
`
${
String
(
hour
).
padStart
(
2
,
'0'
)}
:
${
String
(
minute
).
padStart
(
2
,
'0'
)}
`
const
parseRegistrationTime
=
(
time
:
string
)
=>
{
const
[
hour
=
0
,
minute
=
0
]
=
time
.
split
(
':'
).
map
(
Number
)
return
{
hour
,
minute
,
}
}
const
open
=
async
()
=>
{
const
{
data
}
=
await
getLotteryConfigDetail
()
if
(
!
data
)
{
...
...
@@ -102,7 +114,10 @@ const open = async () => {
id
:
data
.
id
,
openRangeTime
:
[
String
(
data
.
startDate
),
String
(
data
.
endDate
)],
autoCloseWeekend
:
data
.
autoCloseWeekend
,
registrationRangeTime
:
[
String
(
data
.
registrationStartHour
),
String
(
data
.
registrationEndHour
)],
registrationRangeTime
:
[
formatRegistrationTime
(
data
.
registrationStartHour
,
data
.
registrationStartMinute
),
formatRegistrationTime
(
data
.
registrationEndHour
,
data
.
registrationEndMinute
),
],
registrationFee
:
data
.
registrationFee
,
}
}
...
...
@@ -111,12 +126,16 @@ const open = async () => {
const
handleSubmit
=
async
()
=>
{
await
formRef
.
value
?.
validate
()
const
registrationStartTime
=
parseRegistrationTime
(
form
.
value
.
registrationRangeTime
[
0
]
!
)
const
registrationEndTime
=
parseRegistrationTime
(
form
.
value
.
registrationRangeTime
[
1
]
!
)
const
data
=
{
startDate
:
form
.
value
.
openRangeTime
[
0
]
!
,
endDate
:
formatSeconds
(
form
.
value
.
openRangeTime
[
1
]
!
),
autoCloseWeekend
:
form
.
value
.
autoCloseWeekend
,
registrationStartHour
:
form
.
value
.
registrationRangeTime
[
0
]
!
,
registrationEndHour
:
form
.
value
.
registrationRangeTime
[
1
]
!
,
registrationStartHour
:
registrationStartTime
.
hour
,
registrationStartMinute
:
registrationStartTime
.
minute
,
registrationEndHour
:
registrationEndTime
.
hour
,
registrationEndMinute
:
registrationEndTime
.
minute
,
registrationFee
:
form
.
value
.
registrationFee
,
}
loading
.
value
=
true
...
...
src/views/backend/settingsMenu/goodsManage/index.vue
View file @
d66ac723
...
...
@@ -20,7 +20,7 @@
clearable
>
<el-option
v-for=
"item in
r
egionListOptions"
v-for=
"item in
goodsR
egionListOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
...
...
@@ -77,7 +77,7 @@
<el-table-column
prop=
"price"
label=
"兑换所需YA币"
min-width=
"200"
>
</el-table-column>
<el-table-column
prop=
"
show
Name"
label=
"创建人"
min-width=
"200"
/>
<el-table-column
prop=
"
createUser
Name"
label=
"创建人"
min-width=
"200"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
...
...
@@ -147,7 +147,7 @@
<el-form-item
label=
"上架地区"
prop=
"region"
>
<el-select
v-model=
"form.region"
placeholder=
"请选择上架地区"
>
<el-option
v-for=
"item in
r
egionListOptions"
v-for=
"item in
goodsR
egionListOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
...
...
@@ -197,7 +197,7 @@ import type { BackendShopItemDto } from '@/api/backend'
import
{
push
}
from
'notivue'
import
{
useMessageBox
}
from
'@/hooks'
const
{
confirm
}
=
useMessageBox
()
const
goodsRegionListOptions
=
[...
regionListOptions
,
{
label
:
'四地通用'
,
value
:
'四地通用'
}]
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
getShopItemList
)
...
...
src/views/columnSearchList/index.vue
View file @
d66ac723
...
...
@@ -100,7 +100,7 @@
<!-- 底部信息 -->
<div
class=
"flex items-center gap-4 text-13px text-gray-500"
>
<span>
{{ item.showName }}
</span>
<span>
{{ dayjs(item.
create
Time * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span>
<span>
{{ dayjs(item.
publish
Time * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span>
<div
class=
"flex items-center gap-1"
>
<el-icon
class=
"text-sm"
>
<IEpView
/>
...
...
src/views/pointsStore/components/exchangeContent.tsx
View file @
d66ac723
...
...
@@ -5,6 +5,11 @@ import { ShopGoodsTypeEnum, regionListOptions } from '@/constants'
import
type
{
BackendShopItemDto
,
ExchangeGoodsParams
}
from
'@/api'
import
type
{
SetupContext
}
from
'vue'
const
UNIVERSAL_REGION
=
'四地通用'
const
universalRegionOptions
=
regionListOptions
.
filter
((
item
)
=>
[
'深圳'
,
'合肥'
,
'武汉'
,
'长沙'
].
includes
(
item
.
value
),
)
type
ExchangeContentProps
=
{
item
:
BackendShopItemDto
modelValue
:
ExchangeGoodsParams
...
...
@@ -17,7 +22,14 @@ export default function ExchangeContent(
{
item
,
modelValue
}:
ExchangeContentProps
,
context
:
SetupContext
<
ExchangeContentEvents
>
,
)
{
const
totalPrice
=
computed
(()
=>
item
.
price
*
(
modelValue
.
num
||
1
))
const
totalPrice
=
item
.
price
*
(
modelValue
.
num
||
1
)
const
deliveryOfficeOptions
=
item
.
region
===
UNIVERSAL_REGION
?
universalRegionOptions
:
(()
=>
{
const
currentRegion
=
regionListOptions
.
find
((
region
)
=>
region
.
value
===
item
.
region
)
return
currentRegion
?
[
currentRegion
]
:
[{
label
:
item
.
region
,
value
:
item
.
region
}]
})()
return
(
<
div
class=
"py-4"
>
...
...
@@ -58,8 +70,9 @@ export default function ExchangeContent(
}
placeholder=
"请选择办公点"
class=
"w-full"
disabled=
{
item
.
region
!==
UNIVERSAL_REGION
}
>
{
regionList
Options
.
map
((
office
)
=>
(
{
deliveryOffice
Options
.
map
((
office
)
=>
(
<
el
-
option
key=
{
office
.
value
}
label=
{
office
.
label
}
value=
{
office
.
value
}
/>
))
}
</
el
-
select
>
...
...
@@ -94,7 +107,7 @@ export default function ExchangeContent(
</
span
>
<
div
class=
"flex items-baseline gap-0.5"
>
<
span
class=
"text-sm text-orange-400"
>
¥
</
span
>
<
span
class=
"text-2xl font-bold text-orange-500"
>
{
totalPrice
.
value
}
</
span
>
<
span
class=
"text-2xl font-bold text-orange-500"
>
{
totalPrice
}
</
span
>
<
span
class=
"text-xs text-gray-400 ml-1"
>
积分
</
span
>
</
div
>
</
div
>
...
...
src/views/pointsStore/components/exchangeGoodsRecordDilaog.vue
View file @
d66ac723
...
...
@@ -13,7 +13,7 @@
<div
class=
"w-750px flex items-center gap-3"
>
<el-select
v-model=
"searchParams.itemType"
placeholder=
"选择商品类型"
clearable
>
<el-option
label=
"亚声实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
<el-option
label=
"虚拟
装饰
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
<el-option
label=
"虚拟
商品
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
</el-select>
<el-date-picker
...
...
@@ -38,7 +38,7 @@
<el-table-column
prop=
"itemType"
label=
"商品类型"
width=
"100"
align=
"center"
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
?
'亚声实物'
:
'虚拟
装饰
'
}}
{{
scope
.
row
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
?
'亚声实物'
:
'虚拟
商品
'
}}
</
template
>
</el-table-column>
...
...
src/views/pointsStore/components/exchangeYabiRecordDilaog.vue
View file @
d66ac723
...
...
@@ -13,7 +13,7 @@
<div
class=
"w-750px flex items-center gap-3"
>
<!--
<el-select
v-model=
"searchParams.type"
placeholder=
"选择商品类型"
clearable
>
<el-option
label=
"亚声实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
<el-option
label=
"虚拟
装饰
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
<el-option
label=
"虚拟
商品
"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
</el-select>
-->
<el-date-picker
...
...
src/views/pointsStore/index.vue
View file @
d66ac723
...
...
@@ -4,13 +4,13 @@
<BackButton
/>
<!-- 左侧:商品列表区域 -->
<div
class=
"flex-3/4 min-w-0"
>
<!-- 虚拟
装饰
区域 -->
<!-- 虚拟
商品
区域 -->
<div
class=
"bg-white/90 rounded-lg p-6 shadow-lg mb-3 border border-white/60"
>
<div
class=
"flex items-center gap-3 mb-6"
>
<div
class=
"w-1.5 h-7 bg-gradient-to-b from-[#8b5cf6] to-[#6366f1] rounded-full shadow-sm"
></div>
<h2
class=
"text-xl font-bold text-gray-800"
>
虚拟
装饰
</h2>
<h2
class=
"text-xl font-bold text-gray-800"
>
虚拟
商品
</h2>
</div>
<template
v-if=
"virtualGoodsList.length"
>
...
...
@@ -78,27 +78,6 @@
<h2
class=
"text-xl font-bold text-gray-800"
>
亚声实物
</h2>
</div>
<!-- 地区筛选 -->
<div
class=
"flex gap-3 text-sm mb-6 items-center flex-wrap"
>
<span
class=
"text-gray-600 font-medium"
>
地区:
</span>
<button
v-for=
"item in tabs"
:key=
"item.value"
class=
"cursor-pointer px-3 py-1.5 text-sm transition-all relative"
@
click=
"onChangeRegion(item.value)"
:class=
"{
'text-indigo-600 font-medium': realGoodsSearchParams.region === item.value,
'text-gray-600 hover:text-gray-900': realGoodsSearchParams.region !== item.value,
}"
>
{{ item.label }}
<span
v-if=
"realGoodsSearchParams.region === item.value"
class=
"absolute bottom-0 left-0 right-0 h-0.5 bg-gradient-to-b from-[#8b5cf6] to-[#6366f1]"
></span>
</button>
</div>
<
template
v-if=
"realGoodsList.length"
>
<div
class=
"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4"
>
<div
...
...
@@ -211,7 +190,7 @@
<!-- 统计信息(可选) -->
<div
class=
"mt-6 pt-6 border-t border-gray-100 space-y-3"
>
<div
class=
"flex justify-between items-center text-sm"
>
<span
class=
"text-gray-500"
>
虚拟
装饰
</span>
<span
class=
"text-gray-500"
>
虚拟
商品
</span>
<span
class=
"font-medium text-gray-700"
>
{{ virtualGoodsTotal }} 件
</span>
</div>
<div
class=
"flex justify-between items-center text-sm"
>
...
...
@@ -231,7 +210,7 @@
<
script
setup
lang=
"tsx"
>
import
{
exchangeGoods
,
getShopItemList
}
from
'@/api'
import
{
usePageSearch
}
from
'@/hooks'
import
{
regionListOptions
,
ShopGoodsTypeEnum
}
from
'@/constants'
import
{
ShopGoodsTypeEnum
}
from
'@/constants'
import
type
{
ExchangeGoodsParams
,
BackendShopItemDto
}
from
'@/api'
import
ExchangeContent
from
'./components/exchangeContent.tsx'
import
ExchangeGoodsRecordDialog
from
'./components/exchangeGoodsRecordDilaog.vue'
...
...
@@ -242,9 +221,7 @@ import BackButton from '@/components/common/BackButton/index.vue'
import
{
push
}
from
'notivue'
const
yabiStore
=
useYaBiStore
()
const
{
yabiData
}
=
storeToRefs
(
yabiStore
)
const
activeTab
=
ref
(
'深圳'
)
const
tabs
=
ref
(
regionListOptions
)
const
UNIVERSAL_REGION
=
'四地通用'
const
exchangeGoodsRecordDialogRef
=
useTemplateRef
<
InstanceType
<
typeof
ExchangeGoodsRecordDialog
>>
(
'exchangeGoodsRecordDialogRef'
,
...
...
@@ -276,15 +253,9 @@ const {
}
=
usePageSearch
(
getShopItemList
,
{
defaultParams
:
{
itemType
:
ShopGoodsTypeEnum
.
REAL_GOODS
,
region
:
activeTab
.
value
,
},
})
const
onChangeRegion
=
(
region
:
string
)
=>
{
realGoodsSearchParams
.
value
.
region
=
region
realGoodsGoToPage
(
1
)
}
const
onOpenExchangeYabiRecordDialog
=
()
=>
{
exchangeYabiRecordDialogRef
.
value
?.
open
()
}
...
...
@@ -296,12 +267,16 @@ const onOpenExchangeGoodsRecordDialog = () => {
// 兑换商品
const
onExchangeGoods
=
async
(
item
:
BackendShopItemDto
)
=>
{
if
(
item
.
stock
===
0
)
return
push
.
warning
(
'库存为0,不可兑换'
)
const
form
=
ref
<
ExchangeGoodsParams
>
({
itemId
:
item
.
id
,
num
:
1
,
})
if
(
item
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
)
{
form
.
value
.
deliveryInfo
=
'广州'
const
isRealGoods
=
item
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
const
isUniversalRegion
=
item
.
region
===
UNIVERSAL_REGION
if
(
isRealGoods
&&
!
isUniversalRegion
)
{
form
.
value
.
deliveryInfo
=
item
.
region
}
await
ElMessageBox
({
...
...
@@ -320,6 +295,18 @@ const onExchangeGoods = async (item: BackendShopItemDto) => {
return
push
.
error
(
`您的YA币不足,兑换所需
${
item
.
price
*
form
.
value
.
num
}
YA币,当前YA币
${
yabiData
.
value
.
currentValue
}
`
,
)
if
(
isRealGoods
&&
!
form
.
value
.
deliveryInfo
)
return
push
.
warning
(
'请选择配送办公点'
)
if
(
isRealGoods
&&
isUniversalRegion
)
{
try
{
await
ElMessageBox
.
confirm
(
'请确认配送办公点准确性,准确无误可继续提交'
,
'提示'
,
{
confirmButtonText
:
'继续提交'
,
cancelButtonText
:
'返回修改'
,
type
:
'warning'
,
})
}
catch
{
return
}
}
try
{
instance
.
confirmButtonLoading
=
true
await
exchangeGoods
(
form
.
value
)
...
...
src/views/publishLongArticle/index.vue
View file @
d66ac723
...
...
@@ -37,7 +37,7 @@
</
template
>
<
template
v-else
>
<!-- 回显回来可能会有bug 所以需要key 重新渲染一下-->
<WangEditor
:key
v-model=
"form.content"
/>
<WangEditor
:key
v-model=
"form.content"
/>
</
template
>
</el-form-item>
</div>
...
...
src/views/videoSearchList/index.vue
View file @
d66ac723
...
...
@@ -104,7 +104,7 @@
<!-- 底部信息 -->
<div
class=
"flex items-center gap-4 text-13px text-gray-500"
>
<span>
{{ item.showName }}
</span>
<span>
{{ dayjs(item.
create
Time * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span>
<span>
{{ dayjs(item.
publish
Time * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span>
<div
class=
"flex items-center gap-1"
>
<el-icon
class=
"text-sm"
>
<IEpView
/>
...
...
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