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
ea5de822
Commit
ea5de822
authored
Feb 13, 2026
by
lijiabin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【需求 20331】 feat: 完善后台管理页面优化菜单等、完成前后台限时竞拍相关功能
parent
2a7fbb51
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
1779 additions
and
2173 deletions
+1779
-2173
exchangeContent.tsx
src/views/auction/components/exchangeContent.tsx
+104
-0
exchangeGoodsRecordDilaog.vue
src/views/auction/components/exchangeGoodsRecordDilaog.vue
+126
-0
exchangeYabiRecordDilaog.vue
src/views/auction/components/exchangeYabiRecordDilaog.vue
+116
-0
index.vue
src/views/auction/index.vue
+445
-0
index.vue
src/views/backend/carousel/index.vue
+1
-6
index.vue
src/views/backend/caseManage/index.vue
+47
-52
index.vue
src/views/backend/columnSettings/index.vue
+0
-339
index.vue
src/views/backend/columnsMenu/columnManage/index.vue
+27
-30
index.vue
src/views/backend/columnsMenu/interviewManage/index.vue
+35
-32
index.vue
src/views/backend/columnsMenu/videoManage/index.vue
+27
-30
index.vue
src/views/backend/contentsMenu/columnManage/index.vue
+9
-8
index.vue
src/views/backend/contentsMenu/interviewManage/index.vue
+9
-8
index.vue
src/views/backend/contentsMenu/questionManage/index.vue
+9
-8
index.vue
src/views/backend/contentsMenu/videoManage/index.vue
+9
-8
index.vue
src/views/backend/goodsDistribution/index.vue
+120
-41
index.vue
src/views/backend/goodsManage/index.vue
+0
-390
index.vue
src/views/backend/index.vue
+2
-2
index.vue
src/views/backend/manager/index.vue
+0
-452
auctionRecordDialog.vue
...ingsMenu/auctionManage/components/auctionRecordDialog.vue
+49
-0
index.vue
src/views/backend/settingsMenu/auctionManage/index.vue
+487
-0
index.vue
src/views/backend/settingsMenu/goodsManage/index.vue
+46
-51
index.vue
src/views/backend/tags/index.vue
+11
-12
index.vue
src/views/backend/videoManage/index.vue
+0
-363
index.vue
src/views/backend/videoSettings/index.vue
+0
-338
selfActivity.vue
src/views/userPage/components/selfActivity.vue
+98
-0
index.vue
src/views/userPage/index.vue
+2
-3
No files found.
src/views/auction/components/exchangeContent.tsx
0 → 100644
View file @
ea5de822
/**
* 确认兑换商品的弹窗内容
*/
import
{
ShopGoodsTypeEnum
,
regionListOptions
}
from
'@/constants'
import
type
{
BackendShopItemDto
,
ExchangeGoodsParams
}
from
'@/api'
import
type
{
SetupContext
}
from
'vue'
type
ExchangeContentProps
=
{
item
:
BackendShopItemDto
modelValue
:
ExchangeGoodsParams
}
type
ExchangeContentEvents
=
{
'update:modelValue'
(
data
:
ExchangeGoodsParams
):
void
}
export
default
function
ExchangeContent
(
{
item
,
modelValue
}:
ExchangeContentProps
,
context
:
SetupContext
<
ExchangeContentEvents
>
,
)
{
return
(
<
div
class=
"exchange-content py-6 px-4"
>
{
/* 商品图片区域 */
}
<
div
class=
"flex justify-center mb-8"
>
<
div
class=
"relative"
>
<
div
class=
"w-32 h-32 bg-gradient-to-br from-orange-100 to-pink-100 rounded-3xl flex items-center justify-center shadow-lg"
>
<
div
class=
"w-20 h-20 bg-white rounded-lg flex items-center justify-center shadow-sm"
>
<
img
src=
{
item
.
imageUrl
}
alt=
{
item
.
name
}
class=
"w-16 h-16 object-contain"
/>
</
div
>
</
div
>
<
div
class=
"absolute -top-2 -right-2 w-7 h-7 bg-blue-500 rounded-full flex items-center justify-center shadow-md"
>
<
span
class=
"text-white text-sm font-medium"
>
{
item
.
stock
}
</
span
>
</
div
>
</
div
>
</
div
>
{
/* 商品信息 */
}
<
div
class=
"space-y-3 mb-8"
>
<
div
class=
"flex items-center gap-3 px-4"
>
<
div
class=
"w-1.5 h-1.5 bg-gray-400 rounded-full flex-shrink-0"
></
div
>
<
span
class=
"text-gray-600 text-sm min-w-12"
>
名称:
</
span
>
<
span
class=
"font-medium text-gray-900 flex-1"
>
{
item
.
name
}
</
span
>
</
div
>
<
div
class=
"flex items-center gap-3 px-4"
>
<
div
class=
"w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0"
></
div
>
<
span
class=
"text-gray-600 text-sm min-w-12"
>
积分:
</
span
>
<
span
class=
"font-semibold text-orange-500 text-lg"
>
{
item
.
price
}
YA币
</
span
>
</
div
>
</
div
>
{
/* 办公点选择和数量 */
}
{
item
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
&&
(
<
div
class=
" rounded-lg px-5 mx-2 space-y-4"
>
{
/* 办公点选择 */
}
<
div
>
<
label
class=
"text-gray-700 text-sm font-medium mb-2 block"
>
办公点
</
label
>
<
el
-
select
modelValue=
{
modelValue
.
deliveryInfo
}
onUpdate
:
modelValue=
{
(
value
:
string
)
=>
context
.
emit
(
'update:modelValue'
,
{
...
modelValue
,
deliveryInfo
:
value
})
}
placeholder=
"请选择办公点"
class=
"w-full"
>
{
regionListOptions
.
map
((
office
)
=>
(
<
el
-
option
key=
{
office
.
value
}
label=
{
office
.
label
}
value=
{
office
.
value
}
/>
))
}
</
el
-
select
>
</
div
>
{
/* 数量选择 */
}
<
div
>
<
label
class=
"text-gray-700 text-sm font-medium mb-2 block"
>
选择数量
</
label
>
<
el
-
input
-
number
min=
{
1
}
max=
{
item
.
stock
}
modelValue=
{
modelValue
.
num
}
onUpdate
:
modelValue=
{
(
value
:
number
)
=>
context
.
emit
(
'update:modelValue'
,
{
...
modelValue
,
num
:
value
})
}
class=
"w-full"
controls
-
position=
"right"
/>
</
div
>
</
div
>
)
}
</
div
>
)
}
ExchangeContent
.
props
=
{
item
:
{
type
:
Object
as
PropType
<
BackendShopItemDto
>
,
required
:
true
,
},
modelValue
:
{
type
:
Object
as
PropType
<
ExchangeGoodsParams
>
,
required
:
true
,
},
}
ExchangeContent
.
emits
=
{
'update:modelValue'
:
(
value
:
ExchangeGoodsParams
)
=>
value
,
}
src/views/auction/components/exchangeGoodsRecordDilaog.vue
0 → 100644
View file @
ea5de822
<
template
>
<el-dialog
v-model=
"visible"
title=
"商品领取记录"
width=
"1100px"
class=
"exchange-record-dialog"
align-center
destroy-on-close
>
<div
class=
"px-6 py-4"
>
<!-- 搜索筛选区域 - 优化布局 -->
<div
class=
"mb-4 flex items-center gap-3 justify-end"
>
<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-select>
<el-date-picker
v-model=
"timeRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
format=
"YYYY-MM-DD"
value-format=
"x"
clearable
style=
"width: 700px"
/>
<el-button
type=
"primary"
@
click=
"refresh"
style=
"width: 80px"
>
搜索
</el-button>
</div>
</div>
<!-- 表格 - 调整列宽 -->
<el-table
:data=
"list"
stripe
height=
"420"
class=
"w-full"
>
<el-table-column
prop=
"itemName"
label=
"名称"
min-width=
"140"
show-overflow-tooltip
/>
<el-table-column
prop=
"itemType"
label=
"商品类型"
width=
"100"
align=
"center"
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
itemType
===
ShopGoodsTypeEnum
.
REAL_GOODS
?
'亚声实物'
:
'虚拟装饰'
}}
</
template
>
</el-table-column>
<!-- <el-table-column prop="price" label="商品单价" width="100" align="center" /> -->
<el-table-column
prop=
"num"
label=
"兑换数量"
width=
"100"
align=
"center"
/>
<el-table-column
label=
"扣除YA币"
width=
"110"
align=
"center"
>
<
template
#
default=
"scope"
>
<span
class=
"text-red-500 font-semibold"
>
-
{{
scope
.
row
.
price
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"deliveryInfo"
label=
"收货地址"
min-width=
"160"
show-overflow-tooltip
/>
<el-table-column
prop=
"createTime"
label=
"领取时间"
width=
"200"
>
<
template
#
default=
"scope"
>
{{
dayjs
(
scope
.
row
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
</el-table>
<!-- 分页 - 优化对齐 -->
<div
class=
"flex justify-end mt-4"
>
<el-pagination
v-model:current-page=
"searchParams.current"
:page-size=
"searchParams.size"
@
current-change=
"goToPage"
:total=
"total"
layout=
"total, prev, pager, next"
small
/>
</div>
</div>
</el-dialog>
</template>
<
script
setup
lang=
"ts"
>
import
{
usePageSearch
}
from
'@/hooks'
import
{
getExchangeGoodsRecordList
}
from
'@/api'
import
dayjs
from
'dayjs'
import
{
ShopGoodsTypeEnum
}
from
'@/constants'
const
{
total
,
searchParams
,
refresh
,
goToPage
,
list
}
=
usePageSearch
(
getExchangeGoodsRecordList
,
{
immediate
:
false
,
})
const
timeRange
=
computed
({
get
()
{
if
(
!
searchParams
.
value
.
receiveTimeStart
||
!
searchParams
.
value
.
receiveTimeEnd
)
{
return
[]
}
else
{
return
[
searchParams
.
value
.
receiveTimeStart
*
1000
,
searchParams
.
value
.
receiveTimeEnd
*
1000
]
}
},
set
(
value
)
{
console
.
log
(
value
)
if
(
!
value
)
{
searchParams
.
value
.
receiveTimeStart
=
0
searchParams
.
value
.
receiveTimeEnd
=
0
}
else
{
searchParams
.
value
.
receiveTimeStart
=
value
[
0
]
!
/ 100
0
searchParams
.
value
.
receiveTimeEnd
=
value
[
1
]
!
/ 100
0
}
},
})
const
visible
=
shallowRef
(
false
)
const
open
=
()
=>
{
visible
.
value
=
true
refresh
()
}
defineExpose
({
open
,
})
</
script
>
<
style
scoped
></
style
>
src/views/auction/components/exchangeYabiRecordDilaog.vue
0 → 100644
View file @
ea5de822
<
template
>
<el-dialog
v-model=
"visible"
title=
"YA币收支记录"
width=
"1100px"
class=
"exchange-record-dialog"
align-center
destroy-on-close
>
<div
class=
"px-6 py-4"
>
<!-- 搜索筛选区域 - 优化布局 -->
<div
class=
"mb-4 flex items-center gap-3 justify-end"
>
<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-select>
-->
<el-date-picker
v-model=
"timeRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
format=
"YYYY-MM-DD"
value-format=
"x"
clearable
style=
"width: 700px"
/>
<el-button
type=
"primary"
@
click=
"onSearch"
style=
"width: 80px"
>
搜索
</el-button>
</div>
</div>
<!-- 表格 - 调整列宽 -->
<el-table
:data=
"list"
stripe
height=
"420"
class=
"w-full"
>
<el-table-column
prop=
"remark"
label=
"名称"
min-width=
"140"
show-overflow-tooltip
/>
<el-table-column
prop=
"itemType"
label=
"YA币"
width=
"100"
align=
"center"
>
<template
#
default=
"scope"
>
<span
class=
"font-semibold"
:class=
"
{ 'text-red-500': !scope.row.isIncr, 'text-green-500': scope.row.isIncr }"
>
<!--
{{
scope
.
row
.
isIncr
?
'+'
:
'-'
}}
-->
{{
scope
.
row
.
scoreAyabi
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"createdAt"
label=
"时间"
width=
"300"
>
<
template
#
default=
"scope"
>
{{
dayjs
(
scope
.
row
.
createdAt
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
</el-table>
<!-- 分页 - 优化对齐 -->
<div
class=
"flex justify-end mt-4"
>
<el-pagination
v-model:current-page=
"searchParams.current"
:page-size=
"searchParams.size"
@
current-change=
"goToPage"
:total=
"total"
layout=
"total, prev, pager, next"
small
/>
</div>
</div>
</el-dialog>
</template>
<
script
setup
lang=
"ts"
>
import
{
usePageSearch
}
from
'@/hooks'
import
{
getExchangeYabiRecordList
}
from
'@/api'
import
dayjs
from
'dayjs'
const
{
total
,
searchParams
,
refresh
,
goToPage
,
list
}
=
usePageSearch
(
getExchangeYabiRecordList
,
{
immediate
:
false
,
})
const
timeRange
=
computed
({
get
()
{
if
(
!
searchParams
.
value
.
startTime
||
!
searchParams
.
value
.
endTime
)
{
return
[]
}
else
{
return
[
searchParams
.
value
.
startTime
*
1000
,
searchParams
.
value
.
endTime
*
1000
]
}
},
set
(
value
)
{
if
(
!
value
)
{
searchParams
.
value
.
startTime
=
undefined
searchParams
.
value
.
endTime
=
undefined
}
else
{
searchParams
.
value
.
startTime
=
value
[
0
]
!
/ 100
0
searchParams
.
value
.
endTime
=
value
[
1
]
!
/ 100
0
}
},
})
const
visible
=
shallowRef
(
false
)
const
open
=
()
=>
{
visible
.
value
=
true
refresh
()
}
const
onSearch
=
()
=>
{
refresh
()
}
defineExpose
({
open
,
})
</
script
>
<
style
scoped
></
style
>
src/views/auction/index.vue
0 → 100644
View file @
ea5de822
<
script
setup
lang=
"tsx"
>
import
dayjs
from
'dayjs'
import
{
usePageSearch
}
from
'@/hooks'
import
{
AuctionStatusEnum
}
from
'@/constants'
import
{
getAuctionList
,
getUserAuctionCount
,
getAuctionDetail
,
participateAuction
}
from
'@/api'
import
ExchangeGoodsRecordDialog
from
'./components/exchangeGoodsRecordDilaog.vue'
import
ExchangeYabiRecordDialog
from
'./components/exchangeYabiRecordDilaog.vue'
import
type
{
AuctionItemDto
}
from
'@/api'
import
{
useYaBiStore
}
from
'@/stores'
import
{
storeToRefs
}
from
'pinia'
const
yabiStore
=
useYaBiStore
()
const
{
yabiData
}
=
storeToRefs
(
yabiStore
)
const
tabs
=
[
{
label
:
'全部'
,
value
:
undefined
},
{
label
:
'预告中'
,
value
:
AuctionStatusEnum
.
PUBLISHED
},
{
label
:
'竞拍中'
,
value
:
AuctionStatusEnum
.
AUCTIONING
},
{
label
:
'竞拍成功'
,
value
:
AuctionStatusEnum
.
AUCTION_SUCCESS
},
{
label
:
'已流拍'
,
value
:
AuctionStatusEnum
.
AUCTION_FAILED
},
]
let
timer
:
NodeJS
.
Timeout
|
null
=
null
const
{
list
,
goToPage
,
changePageSize
,
searchParams
,
total
,
refresh
}
=
usePageSearch
(
getAuctionList
,
{
defaultParams
:
{
status
:
undefined
,
},
formatList
(
list
)
{
return
list
.
map
((
item
)
=>
{
item
.
remainingTime
=
getCountdown
(
item
.
endTime
)
return
item
})
},
success
(
list
)
{
if
(
timer
)
clearInterval
(
timer
)
timer
=
setInterval
(()
=>
{
list
.
value
.
forEach
((
item
)
=>
{
item
.
remainingTime
=
getCountdown
(
item
.
endTime
)
})
},
1000
)
},
},
)
const
exchangeGoodsRecordDialogRef
=
useTemplateRef
(
'exchangeGoodsRecordDialogRef'
)
const
exchangeYabiRecordDialogRef
=
useTemplateRef
(
'exchangeYabiRecordDialogRef'
)
const
getCountdown
=
(
targetTimestamp
:
number
)
=>
{
let
diff
=
dayjs
.
unix
(
targetTimestamp
).
diff
(
dayjs
(),
'second'
)
if
(
diff
<=
0
)
{
return
'0天 00:00:00'
}
const
days
=
Math
.
floor
(
diff
/
86400
)
diff
%=
86400
const
hours
=
Math
.
floor
(
diff
/
3600
)
diff
%=
3600
const
minutes
=
Math
.
floor
(
diff
/
60
)
const
seconds
=
diff
%
60
return
`
${
days
}
天
${
String
(
hours
).
padStart
(
2
,
'0'
)}
时
${
String
(
minutes
).
padStart
(
2
,
'0'
)}
分
${
String
(
seconds
).
padStart
(
2
,
'0'
)}
秒`
}
const
onChangeStatus
=
(
status
:
AuctionStatusEnum
|
undefined
)
=>
{
searchParams
.
value
.
status
=
status
refresh
()
}
const
onOpenExchangeYabiRecordDialog
=
()
=>
{
exchangeYabiRecordDialogRef
.
value
?.
open
()
}
// 根据状态计算角标样式 (从之前的 AuctionPage.vue 复制)
const
getBadgeClass
=
(
status
:
AuctionStatusEnum
)
=>
{
switch
(
status
)
{
case
AuctionStatusEnum
.
PUBLISHED
:
return
'bg-amber-100 text-amber-700'
case
AuctionStatusEnum
.
AUCTION_FAILED
:
return
'bg-gray-100 text-gray-500'
case
AuctionStatusEnum
.
AUCTIONING
:
default
:
return
'bg-gradient-to-r from-indigo-500 to-purple-600 text-white'
}
}
const
onBid
=
async
(
item
:
AuctionItemDto
)
=>
{
const
isOver
=
await
getUserAuctionCount
(
item
.
id
)
if
(
!
isOver
)
return
ElMessageBox
.
confirm
(
`您已达到竞拍次数限制
${
item
.
bidLimit
}
次,不可再参与竞拍`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
showCancelButton
:
false
,
showConfirmButton
:
false
,
})
const
{
data
}
=
await
getAuctionDetail
(
item
.
id
)
console
.
log
(
data
,
'data'
)
const
val
=
ref
(
0
)
ElMessageBox
.
confirm
(
'确定参与竞拍吗?'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
message
:
()
=>
(
<
div
class
=
"space-y-12px text-gray-700"
>
{
/* 作品名称 */
}
<
div
class
=
"text-16px font-600 text-gray-900"
>
{
item
.
name
}
<
/div
>
{
/* 规则说明 */
}
<
div
class
=
"text-12px leading-18px text-gray-500 bg-gray-50 rounded-6px p-10px"
>
竞拍后将暂时扣除您出价的
YA
币,若您的出价被超越,
YA
币将自动退回
<
/div
>
{
/* 当前竞拍信息 */
}
<
div
class
=
"space-y-6px"
>
{
data
.
currentPrice
?
(
<
div
class
=
"flex items-center justify-between"
>
<
span
class
=
"text-gray-500"
>
当前最高出价
<
/span
>
<
span
class
=
"text-orange-500 font-600"
>
{
data
.
currentPrice
}
YA
币
<
/span
>
<
/div
>
)
:
(
<
div
class
=
"text-gray-500"
>
当前暂未有人出价
<
/div
>
)}
<
div
class
=
"flex items-center justify-between"
>
<
span
class
=
"text-gray-500"
>
单人出价上限
<
/span
>
<
span
class
=
"text-gray-700"
>
{
item
.
bidLimit
}
次
<
/span
>
<
/div
>
<
/div
>
{
/* 出价输入 */
}
<
div
class
=
"space-y-6px flex items-center justify-between"
>
<
div
class
=
"text-gray-500"
>
您的出价
<
/div
>
<
el
-
input
-
number
v
-
model
=
{
val
.
value
}
controls
-
position
=
"right"
class
=
"w-50%!"
placeholder
=
"请输入 YA 币数量"
/>
<
/div
>
{
/* 余额提示 */
}
<
div
class
=
"flex items-center justify-end text-12px text-gray-500 rounded-6px p-8px"
>
<
span
>
当前可用
{
yabiData
.
value
.
currentValue
}
YA
币
<
/span
>
<
/div
>
<
/div
>
),
showCancelButton
:
true
,
showConfirmButton
:
true
,
beforeClose
:
async
(
action
,
instance
,
done
)
=>
{
if
(
action
!==
'confirm'
)
{
done
()
}
else
{
if
(
val
.
value
>
yabiData
.
value
.
currentValue
)
return
ElMessage
.
error
(
'您的YA币余额不足'
)
if
(
val
.
value
<
data
.
minIncrement
+
(
data
.
currentPrice
||
data
.
startingPrice
))
return
ElMessage
.
error
(
'出价必须大于等于前最高出价+最低加价幅度'
)
instance
.
confirmButtonLoading
=
true
instance
.
confirmButtonText
=
'Loading...'
try
{
await
participateAuction
(
item
.
id
,
val
.
value
)
refresh
()
yabiStore
.
fetchYaBiData
()
done
()
}
catch
(
error
)
{
console
.
log
(
error
)
refresh
()
}
finally
{
instance
.
confirmButtonLoading
=
false
instance
.
confirmButtonText
=
'确定'
}
}
},
})
}
</
script
>
<
template
>
<div>
<div
class=
"flex gap-6"
>
<div
class=
"flex-3/4 min-w-0"
>
<div
class=
"bg-white/90 backdrop-blur-sm rounded-2xl p-6 shadow-lg 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-[--un-gradient-from] to-[--un-gradient-to] rounded-full shadow-sm"
style=
"--un-gradient-from: #8b5cf6; --un-gradient-to: #6366f1"
></div>
<h2
class=
"text-xl font-bold text-gray-800"
>
限时竞拍
</h2>
</div>
<div
class=
"flex gap-3 text-sm mb-3 items-center flex-wrap"
>
<span
class=
"text-gray-600 font-medium"
>
商品名称:
</span>
<el-input
size=
"default"
class=
"w-70"
v-model=
"searchParams.name"
placeholder=
"请输入商品名称"
/>
<el-button
class=
"rounded-lg"
size=
"default"
type=
"primary"
@
click=
"refresh"
>
搜索
</el-button
>
</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=
"onChangeStatus(item.value)"
:class=
"
{
'text-indigo-600 font-medium': searchParams.status === item.value,
'text-gray-600 hover:text-gray-900': searchParams.status !== item.value,
}"
>
{{
item
.
label
}}
<span
v-if=
"searchParams.status === item.value"
class=
"absolute bottom-0 left-0 right-0 h-0.5 bg-gradient-to-b from-[--un-gradient-from] to-[--un-gradient-to]"
style=
"--un-gradient-from: #8b5cf6; --un-gradient-to: #6366f1"
></span>
</button>
</div>
<template
v-if=
"list.length"
>
<!-- 卡片网格 -->
<div
class=
"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-6"
>
<div
v-for=
"item in list"
:key=
"item.id"
class=
"card group relative bg-white rounded-xl overflow-hidden border-2 border-solid border-transparent shadow-lg hover:border-blue-500 hover:shadow-xl transition-all duration-300 cursor-pointer transform hover:-translate-y-1"
:class=
"
{ 'filter-grayscale-30': item.status === AuctionStatusEnum.AUCTION_FAILED }"
>
<!-- 状态角标 -->
<div
class=
"absolute top-2 left-2 z-2 text-xs font-semibold px-2.5 py-1 rounded-full tracking-wide"
:class=
"getBadgeClass(item.status)"
>
{{
tabs
.
find
((
option
)
=>
option
.
value
===
item
.
status
)?.
label
}}
</div>
<!-- 图片容器 -->
<div
class=
"card-img-wrap w-full aspect-6/5 bg-gradient-to-br from-blue-50 to-purple-50 flex items-center justify-center relative overflow-hidden"
>
<img
:src=
"item.imageUrl"
class=
"w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
/>
<!-- 悬浮层 -->
<!--
<div
class=
"absolute inset-0 bg-black/0 group-hover:bg-black/15 transition-all duration-300 flex items-center justify-center opacity-0 group-hover:opacity-100"
>
<span
class=
"bg-white px-4 py-2 rounded-full text-sm font-medium text-blue-600 shadow-md transition-all duration-300"
>
查看详情
</span>
</div>
-->
</div>
<!-- 内容区 -->
<div
class=
"card-body p-5 flex flex-col gap-2"
>
<!-- 标题 -->
<h3
class=
"text-[15px] font-semibold text-gray-900 leading-snug line-clamp-1"
>
{{
item
.
name
}}
</h3>
<!-- 描述 -->
<p
class=
"text-xs text-gray-500 leading-relaxed line-clamp-1"
>
<el-popover
:content=
"item.description"
placement=
"top-start"
width=
"300"
>
<template
#
reference
>
{{
item
.
description
}}
</
template
>
</el-popover>
</p>
<!-- 规格 -->
<div
class=
"flex items-center gap-1 text-xs text-gray-600"
>
<span
class=
"text-gray-400"
>
规格
</span>
<span
class=
"text-gray-700 font-medium"
>
{{ item.specification }}
</span>
</div>
<!-- 剩余时间(单独一行,重要) -->
<div
class=
"text-xs text-gray-500 mt-1"
:style=
"{
opacity: item.status === AuctionStatusEnum.AUCTIONING ? 1 : 0,
}"
>
⏱ 拍卖剩余:{{ item.remainingTime }}
</div>
<!-- 底部价格 + 按钮 -->
<div
class=
"flex items-end justify-between gap-2"
>
<div
class=
"flex flex-col"
>
<div
class=
"flex items-baseline gap-1"
>
<span
class=
"text-xs text-gray-400"
>
起拍
</span>
<span
class=
"text-lg font-bold text-red-500"
>
{{ item.startingPrice }}
</span>
<span
class=
"text-xs text-gray-500"
>
YA币
</span>
</div>
<div
class=
"text-xs text-gray-400"
>
最低加价
<span
class=
"text-gray-600 font-medium"
>
{{ item.minIncrement }}
</span>
YA币
</div>
</div>
<el-button
v-if=
"item.status === AuctionStatusEnum.AUCTIONING"
type=
"primary"
size=
"small"
class=
"bg-gradient-to-r from-indigo-500 to-purple-600 text-white border-none px-4 py-2 rounded-lg shadow-md hover:shadow-lg transition-all"
@
click
.
stop=
"onBid(item)"
>
参与竞拍
</el-button>
</div>
</div>
</div>
</div>
<div
class=
"flex justify-end mt-4"
>
<div
class=
"bg-gray-50 rounded-xl shadow-sm border border-gray-200 p-2"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
@
current-change=
"goToPage"
@
size-change=
"changePageSize"
/>
</div>
</div>
</template>
<div
v-else
class=
"flex justify-center items-center py-12"
>
<el-empty
description=
"暂无"
/>
</div>
</div>
</div>
<!-- 右侧:信息面板 -->
<div
class=
"flex-1/4 space-y-6"
>
<!-- YA币信息卡片 -->
<div
class=
"bg-white/90 backdrop-blur-sm rounded-2xl p-6 shadow-lg border border-white/60 sticky top-[52px]"
>
<div
class=
"text-center mb-6"
>
<div
class=
"text-gray-500 text-sm mb-2"
>
当前YA币
</div>
<div
class=
"text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600 text-5xl font-bold"
>
{{ yabiData.currentValue }}
</div>
</div>
<!-- 操作按钮 -->
<div
class=
"space-y-3 mb-6"
>
<button
class=
"cursor-pointer w-full px-4 py-3 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl text-sm font-medium hover:shadow-lg hover:scale-[1.02] transition-all duration-300"
@
click=
"onOpenExchangeYabiRecordDialog"
>
YA币收支记录
</button>
<!-- <button
class="cursor-pointer w-full px-4 py-3 bg-white text-gray-700 rounded-xl text-sm font-medium border border-gray-200 hover:border-blue-400 hover:shadow-md transition-all duration-300"
@click="onOpenExchangeGoodsRecordDialog"
>
商品领取列表
</button> -->
</div>
<!-- 温馨提示 -->
<!-- <div class="bg-amber-50 border border-amber-200/60 rounded-xl p-4">
<div class="flex items-start gap-2">
<svg
class="w-5 h-5 text-amber-500 flex-shrink-0 mt-0.5"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
clip-rule="evenodd"
/>
</svg>
<div class="text-sm text-gray-700">
<div class="font-medium mb-1">温馨提示</div>
<p class="text-xs leading-relaxed">
实物商品兑换后,请耐心等待各地人才发展部伙伴统一发放安排
</p>
</div>
</div>
</div> -->
<!-- <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="font-medium text-gray-700">{{ total }} 件</span>
</div>
</div> -->
</div>
</div>
</div>
<ExchangeGoodsRecordDialog
ref=
"exchangeGoodsRecordDialogRef"
/>
<ExchangeYabiRecordDialog
ref=
"exchangeYabiRecordDialogRef"
/>
</div>
</template>
<
style
scoped
>
/* 已结束卡片置灰 */
.card.filter-grayscale-30
{
filter
:
grayscale
(
30%
);
}
/* 图片光圈装饰 (UnoCSS 复杂渐变伪元素不易直接实现,保留为 scoped CSS) */
.card-img-wrap
::before
{
content
:
''
;
position
:
absolute
;
width
:
120px
;
height
:
120px
;
border-radius
:
50%
;
background
:
radial-gradient
(
circle
,
rgba
(
139
,
92
,
246
,
0.12
)
0%
,
transparent
70%
);
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
transition
:
transform
0.3s
ease
;
z-index
:
0
;
/* 确保在图片下方 */
}
/* 悬浮时光圈放大效果 */
.card
:hover
.card-img-wrap
::before
{
transform
:
translate
(
-50%
,
-50%
)
scale
(
1.1
);
}
.bid-btn.el-button.is-disabled
{
--el-button-bg-color
:
#d1d5db
!important
;
/* gray-300 */
--el-button-text-color
:
#6b7280
!important
;
/* gray-500 */
background
:
#d1d5db
!important
;
/* fallback */
color
:
#6b7280
!important
;
/* fallback */
box-shadow
:
none
!important
;
cursor
:
not-allowed
!important
;
transform
:
none
!important
;
}
.bid-btn.el-button.is-disabled
:hover
{
transform
:
none
!important
;
box-shadow
:
none
!important
;
background
:
#d1d5db
!important
;
color
:
#6b7280
!important
;
}
</
style
>
src/views/backend/carousel/index.vue
View file @
ea5de822
...
@@ -359,14 +359,9 @@ onMounted(() => {
...
@@ -359,14 +359,9 @@ onMounted(() => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.add-btn
{
margin-left
:
auto
;
}
}
}
//
表格区域
//
表格区域
.table-section
{
.table-section
{
flex
:
1
;
flex
:
1
;
...
...
src/views/backend/caseManage/index.vue
View file @
ea5de822
...
@@ -3,56 +3,50 @@
...
@@ -3,56 +3,50 @@
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
<el-input
v-model=
"searchParams.title"
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
placeholder=
"请输入栏目标题"
class=
"w-200px"
class=
"w-200px"
></el-input>
></el-input>
<!-- 审核状态 -->
<!-- 审核状态 -->
<el-select
<el-select
v-model=
"searchParams.isAudit"
v-model=
"searchParams.isAudit"
placeholder=
"请选择审核状态"
placeholder=
"请选择审核状态"
class=
"search-select mx-12px"
class=
"search-select"
clearable
clearable
>
>
<el-option
<el-option
v-for=
"item in auditTypeListOptions"
v-for=
"item in auditTypeListOptions"
:key=
"item.value"
:key=
"item.value"
:label=
"item.label"
:label=
"item.label"
:value=
"item.value"
:value=
"item.value"
/>
/>
</el-select>
</el-select>
<!-- 发布状态 -->
<!-- 发布状态 -->
<el-select
<el-select
v-model=
"searchParams.isUse"
v-model=
"searchParams.isUse"
placeholder=
"请选择发布状态"
placeholder=
"请选择发布状态"
class=
"search-select mr-12px"
class=
"search-select"
clearable
clearable
>
>
<el-option
<el-option
v-for=
"item in usageStatusListOptions"
v-for=
"item in usageStatusListOptions"
:key=
"item.value"
:key=
"item.value"
:label=
"item.label"
:label=
"item.label"
:value=
"item.value"
:value=
"item.value"
/>
/>
</el-select>
</el-select>
<el-button
type=
"primary"
@
click=
"refresh"
>
<div>
<el-icon><IEpSearch
/></el-icon>
<el-button
type=
"primary"
@
click=
"refresh"
>
搜索
</el-button
<el-icon><IEpSearch
/></el-icon>
>
搜索
</el-button
<el-button
@
click=
"reset"
>
重置
</el-button>
>
<el-button
@
click=
"reset"
>
重置
</el-button>
<ImportExcelBtn
:api=
"importCaseExcel"
@
success=
"refresh"
@
error=
"handleError"
/>
</div>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
</div>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
<div
class=
"flex justify-end"
>
<UploadExcel
:api=
"importCaseExcel"
@
success=
"refresh"
@
error=
"handleError"
/>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -297,7 +291,7 @@ import {
...
@@ -297,7 +291,7 @@ import {
AuditStatusEnum
,
AuditStatusEnum
,
UsageStatusEnum
,
UsageStatusEnum
,
}
from
'@/constants'
}
from
'@/constants'
import
UploadExcel
from
'@/components/common/UploadExcel
/index.vue'
import
ImportExcelBtn
from
'@/components/common/ImportExcelBtn
/index.vue'
import
dayjs
from
'dayjs'
import
dayjs
from
'dayjs'
import
ErrorListDialog
from
'./components/errorListDialog.vue'
import
ErrorListDialog
from
'./components/errorListDialog.vue'
import
EditDialog
from
'./components/editDialog.vue'
import
EditDialog
from
'./components/editDialog.vue'
...
@@ -397,8 +391,9 @@ const handleError = (list: BackendCaseListItemDto[]) => {
...
@@ -397,8 +391,9 @@ const handleError = (list: BackendCaseListItemDto[]) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
flex-shrink
:
0
;
flex-shrink
:
0
;
gap
:
12px
0
;
.search-select
{
.search-select
{
width
:
200px
;
width
:
200px
;
...
...
src/views/backend/columnSettings/index.vue
deleted
100644 → 0
View file @
2a7fbb51
<!-- views/backend/official/index.vue -->
<
template
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
class=
"w-200px"
clearable
></el-input>
<el-select
v-model=
"searchParams.status"
placeholder=
"请选择发布状态"
class=
"search-select"
clearable
>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
</el-select>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
</div>
<div
class=
"flex justify-end"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
<!-- 表格区域 -->
<div
class=
"table-section"
>
<!-- 表格 -->
<div
class=
"table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"list"
height=
"100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
>
</el-table-column>
<el-table-column
prop=
"sort"
label=
"栏目顺序"
width=
"180"
>
</el-table-column>
<el-table-column
prop=
"title"
label=
"栏目名称"
min-width=
"200"
/>
<el-table-column
prop=
"postCount"
label=
"栏目帖子数量"
min-width=
"200"
/>
<el-table-column
prop=
"color"
label=
"颜色"
width=
"300"
>
<template
#
default=
"
{ row }">
<div
class=
"color-cell"
>
<div
class=
"color-block"
:style=
"
{ backgroundColor: row.color }" />
<span
class=
"color-text"
>
{{
row
.
color
}}
</span>
</div>
</
template
>
</el-table-column>
<el-table-column
prop=
"createUserId"
label=
"创建人"
min-width=
"200"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
{{
dayjs
(
row
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"状态"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<el-switch
:model-value=
"row.status"
:active-value=
"1"
:inactive-value=
"0"
@
change=
"handleStatusChange(row)"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"primary"
link
@
click=
"handleEdit(row)"
>
编辑
</el-button>
<el-button
type=
"danger"
link
@
click=
"handleDelete(row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div
class=
"pagination-wrapper"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
:page-sizes=
"[10, 20, 30]"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
/>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"500px"
:close-on-click-modal=
"false"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
label-width=
"80px"
>
<el-form-item
label=
"标题"
prop=
"title"
>
<el-input
v-model=
"form.title"
placeholder=
"请输入标题"
/>
</el-form-item>
<el-form-item
label=
"颜色"
prop=
"color"
>
<el-color-picker
v-model=
"form.color"
/>
<span
class=
"color-value"
>
{{ form.color }}
</span>
</el-form-item>
<el-form-item
label=
"排序"
prop=
"sort"
>
<el-input-number
v-model=
"form.sort"
:min=
"0"
:max=
"100"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
保存
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
listOfCultureColumn
,
addOrUpdateColumn
,
deleteColumn
,
hideColumn
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendColumnListItemDto
,
AddOrUpdateColumnDto
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
listOfCultureColumn
,
{
defaultParams
:
{
type
:
'column'
,
},
})
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
const
formRef
=
ref
<
FormInstance
>
()
// 表单数据
const
[
form
,
resetForm
]
=
useResetData
<
AddOrUpdateColumnDto
>
({
title
:
''
,
color
:
'#000000'
,
id
:
undefined
,
sort
:
0
,
type
:
'column'
,
})
// 表单验证规则
const
formRules
:
FormRules
=
{
title
:
[{
required
:
true
,
message
:
'请输入标题'
,
trigger
:
'blur'
}],
color
:
[{
required
:
true
,
message
:
'请选择颜色'
,
trigger
:
'change'
}],
sort
:
[{
required
:
true
,
message
:
'请输入排序'
,
trigger
:
'blur'
}],
}
// 新增
const
handleAdd
=
()
=>
{
resetForm
()
dialogVisible
.
value
=
true
}
// 编辑
const
handleEdit
=
(
row
:
BackendColumnListItemDto
)
=>
{
resetForm
()
form
.
value
=
{
title
:
row
.
title
,
color
:
row
.
color
,
id
:
row
.
id
,
sort
:
row
.
sort
,
type
:
'column'
,
}
dialogVisible
.
value
=
true
}
// 状态改变
const
handleStatusChange
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
await
hideColumn
([
row
.
id
])
refresh
()
}
// 删除
const
handleDelete
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除标签"
${
row
.
title
}
"吗?`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
await
deleteColumn
([
row
.
id
])
ElMessage
.
success
(
'删除成功'
)
refresh
()
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
'删除失败'
)
}
}
}
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
try
{
await
formRef
.
value
.
validate
()
if
(
form
.
value
.
id
)
{
await
addOrUpdateColumn
(
form
.
value
)
}
else
{
await
addOrUpdateColumn
(
form
.
value
)
}
ElMessage
.
success
(
form
.
value
.
id
?
'编辑成功'
:
'新增成功'
)
dialogVisible
.
value
=
false
if
(
form
.
value
.
id
)
{
search
()
}
else
{
refresh
()
}
}
catch
(
error
)
{
console
.
error
(
'表单验证失败:'
,
error
)
}
}
const
selectedRows
=
ref
<
BackendColumnListItemDto
[]
>
([])
// 选择
const
handleSelectionChange
=
(
selection
:
BackendColumnListItemDto
[])
=>
{
selectedRows
.
value
=
selection
}
// 批量发布/隐藏
const
handleBatchPublish
=
async
()
=>
{
await
hideColumn
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
selectedRows
.
value
=
[]
ElMessage
.
success
(
'发布/隐藏成功'
)
}
// 批量删除
const
handleBatchDelete
=
async
()
=>
{
await
deleteColumn
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
selectedRows
.
value
=
[]
ElMessage
.
success
(
'删除成功'
)
}
</
script
>
<
style
scoped
lang=
"scss"
>
.official-tag-page
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
//
搜索区域
.search-section
{
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
gap
:
12px
;
flex-shrink
:
0
;
.search-select
{
width
:
200px
;
}
}
//
表格区域
.table-section
{
flex
:
1
;
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-direction
:
column
;
min-height
:
0
;
}
.table-wrapper
{
flex
:
1
;
min-height
:
0
;
.color-cell
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
.color-block
{
width
:
100%
;
height
:
36px
;
border-radius
:
4px
;
border
:
1px
solid
#e5e7eb
;
flex
:
1
;
}
.color-text
{
color
:
#fff
;
font-size
:
14px
;
font-weight
:
500
;
position
:
absolute
;
left
:
50%
;
transform
:
translateX
(
-50%
);
text-shadow
:
0
0
3px
rgba
(
0
,
0
,
0
,
0.5
);
}
}
}
.pagination-wrapper
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
16px
;
flex-shrink
:
0
;
}
//
对话框内的颜色显示
.color-value
{
margin-left
:
12px
;
color
:
#606266
;
font-family
:
monospace
;
}
.btn-icon
{
margin-right
:
4px
;
}
</
style
>
src/views/backend/columnsMenu/columnManage/index.vue
View file @
ea5de822
...
@@ -3,35 +3,31 @@
...
@@ -3,35 +3,31 @@
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
<el-input
v-model=
"searchParams.title"
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
placeholder=
"请输入栏目标题"
class=
"w-200px"
class=
"w-200px"
clearable
clearable
></el-input>
></el-input>
<el-select
<el-select
v-model=
"searchParams.status"
v-model=
"searchParams.status"
placeholder=
"请选择发布状态"
placeholder=
"请选择发布状态"
class=
"search-select mx-12px"
class=
"search-select"
clearable
clearable
>
>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
</el-select>
</el-select>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
</div>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
<div
class=
"flex justify-end"
>
新增
<el-button
type=
"primary"
@
click=
"handleAdd"
>
</el-button>
<el-icon><Plus
/></el-icon>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
新增
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -271,7 +267,8 @@ const handleBatchDelete = async () => {
...
@@ -271,7 +267,8 @@ const handleBatchDelete = async () => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/columnsMenu/interviewManage/index.vue
View file @
ea5de822
...
@@ -3,35 +3,37 @@
...
@@ -3,35 +3,37 @@
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
<el-input
v-model=
"searchParams.title"
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
placeholder=
"请输入栏目标题"
class=
"w-200px"
class=
"w-200px"
clearable
clearable
></el-input>
></el-input>
<el-select
v-model=
"searchParams.status"
<el-select
placeholder=
"请选择发布状态"
v-model=
"searchParams.status"
class=
"search-select mx-12px"
placeholder=
"请选择发布状态"
clearable
class=
"search-select"
>
clearable
<el-option
label=
"发布"
:value=
"1"
/>
>
<el-option
label=
"隐藏"
:value=
"0"
/>
<el-option
label=
"发布"
:value=
"1"
/>
</el-select>
<el-option
label=
"隐藏"
:value=
"0"
/>
<el-button
type=
"primary"
@
click=
"refresh"
>
</el-select>
<el-icon><IEpSearch
/></el-icon>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
搜索
<el-button
@
click=
"reset"
>
重置
</el-button>
</el-button>
</div>
<el-button
type=
"primary"
@
click=
"refresh"
>
<el-icon><Search
/></el-icon>
<div
class=
"flex justify-end"
>
搜索
<el-button
type=
"primary"
@
click=
"handleAdd"
>
</el-button>
<el-icon><Plus
/></el-icon>
<el-button
@
click=
"reset"
>
重置
</el-button>
新增
</el-button>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-icon><IEpPlus
/></el-icon>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
新增
</div>
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -120,7 +122,7 @@
...
@@ -120,7 +122,7 @@
<
template
#
footer
>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
<el-icon
class=
"btn-icon"
><
IEp
Upload
/></el-icon>
保存
保存
</el-button>
</el-button>
</
template
>
</
template
>
...
@@ -129,7 +131,7 @@
...
@@ -129,7 +131,7 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
Search
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
listOfCultureColumn
,
addOrUpdateColumn
,
deleteColumn
,
hideColumn
}
from
'@/api/backend'
import
{
listOfCultureColumn
,
addOrUpdateColumn
,
deleteColumn
,
hideColumn
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
...
@@ -271,7 +273,8 @@ const handleBatchDelete = async () => {
...
@@ -271,7 +273,8 @@ const handleBatchDelete = async () => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/columnsMenu/videoManage/index.vue
View file @
ea5de822
...
@@ -2,35 +2,31 @@
...
@@ -2,35 +2,31 @@
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
<el-input
v-model=
"searchParams.title"
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
placeholder=
"请输入栏目标题"
class=
"w-200px"
class=
"w-200px"
clearable
clearable
></el-input>
></el-input>
<el-select
<el-select
v-model=
"searchParams.status"
v-model=
"searchParams.status"
placeholder=
"请选择发布状态"
placeholder=
"请选择发布状态"
class=
"search-select mx-12px"
class=
"search-select"
clearable
clearable
>
>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
</el-select>
</el-select>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
</div>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
<div
class=
"flex justify-end"
>
新增
<el-button
type=
"primary"
@
click=
"handleAdd"
>
</el-button>
<el-icon><Plus
/></el-icon>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
新增
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -270,7 +266,8 @@ const handleBatchDelete = async () => {
...
@@ -270,7 +266,8 @@ const handleBatchDelete = async () => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/contentsMenu/columnManage/index.vue
View file @
ea5de822
...
@@ -112,13 +112,13 @@ const handleShowContent = (row: ArticleItemDto) => {
...
@@ -112,13 +112,13 @@ const handleShowContent = (row: ArticleItemDto) => {
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<
div
class=
"flex-1 flex gap-2"
>
<
el-input
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入标题"
class=
"w-200px"
></el-input>
v-model=
"searchParams.title"
<div>
placeholder=
"请输入标题"
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
class=
"w-200px mr-12px"
<el-button
@
click=
"reset"
>
重置
</el-button
>
></el-input
>
</div
>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button
>
<
/div
>
<
el-button
@
click=
"reset"
>
重置
</el-button
>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -251,7 +251,8 @@ const handleShowContent = (row: ArticleItemDto) => {
...
@@ -251,7 +251,8 @@ const handleShowContent = (row: ArticleItemDto) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/contentsMenu/interviewManage/index.vue
View file @
ea5de822
...
@@ -112,13 +112,13 @@ const handleShowContent = (row: ArticleItemDto) => {
...
@@ -112,13 +112,13 @@ const handleShowContent = (row: ArticleItemDto) => {
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<
div
class=
"flex-1 flex gap-2"
>
<
el-input
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入标题"
class=
"w-200px"
></el-input>
v-model=
"searchParams.title"
<div>
placeholder=
"请输入标题"
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
class=
"w-200px mr-12px"
<el-button
@
click=
"reset"
>
重置
</el-button
>
></el-input
>
</div
>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button
>
<
/div
>
<
el-button
@
click=
"reset"
>
重置
</el-button
>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -251,7 +251,8 @@ const handleShowContent = (row: ArticleItemDto) => {
...
@@ -251,7 +251,8 @@ const handleShowContent = (row: ArticleItemDto) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/contentsMenu/questionManage/index.vue
View file @
ea5de822
...
@@ -112,13 +112,13 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
...
@@ -112,13 +112,13 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<
div
class=
"flex-1 flex gap-2"
>
<
el-input
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入标题"
class=
"w-200px"
></el-input>
v-model=
"searchParams.title"
<div>
placeholder=
"请输入标题"
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
class=
"w-200px mr-12px"
<el-button
@
click=
"reset"
>
重置
</el-button
>
></el-input
>
</div
>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button
>
<
/div
>
<
el-button
@
click=
"reset"
>
重置
</el-button
>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -259,7 +259,8 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
...
@@ -259,7 +259,8 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/contentsMenu/videoManage/index.vue
View file @
ea5de822
...
@@ -102,13 +102,13 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
...
@@ -102,13 +102,13 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<
div
class=
"flex-1 flex gap-2"
>
<
el-input
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入标题"
class=
"w-200px"
></el-input>
v-model=
"searchParams.title"
<div>
placeholder=
"请输入标题"
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
class=
"w-200px mr-12px"
<el-button
@
click=
"reset"
>
重置
</el-button
>
></el-input
>
</div
>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button
>
<
/div
>
<
el-button
@
click=
"reset"
>
重置
</el-button
>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -252,7 +252,8 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
...
@@ -252,7 +252,8 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/goodsDistribution/index.vue
View file @
ea5de822
...
@@ -2,36 +2,43 @@
...
@@ -2,36 +2,43 @@
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
<el-input
v-model=
"searchParams.itemName"
v-model=
"searchParams.itemName"
placeholder=
"请输入商品名称"
placeholder=
"请输入商品名称"
class=
"w-200px"
class=
"w-200px"
></el-input>
></el-input>
<el-select
<el-select
v-model=
"searchParams.status"
v-model=
"searchParams.status"
placeholder=
"请选择发布状态"
placeholder=
"请选择发布状态"
class=
"search-select mx-12px"
class=
"search-select"
clearable
clearable
>
>
<el-option
label=
"待发货"
:value=
"0"
/>
<el-option
label=
"待发货"
:value=
"0"
/>
<el-option
label=
"已发货"
:value=
"1"
/>
<el-option
label=
"已发货"
:value=
"1"
/>
<el-option
label=
"已取消"
:value=
"2"
/>
<el-option
label=
"已取消"
:value=
"2"
/>
</el-select>
</el-select>
<el-select
<el-select
v-model=
"searchParams.source"
v-model=
"searchParams.source"
placeholder=
"请选择来源"
placeholder=
"请选择来源"
class=
"search-select"
class=
"search-select"
clearable
clearable
>
>
<el-option
label=
"商城"
:value=
"1"
/>
<el-option
label=
"商城"
:value=
"1"
/>
<el-option
label=
"大转盘"
:value=
"2"
/>
<el-option
label=
"大转盘"
:value=
"2"
/>
<el-option
label=
"每日抽奖"
:value=
"3"
/>
<el-option
label=
"每日抽奖"
:value=
"3"
/>
</el-select>
</el-select>
<el-button
type=
"primary"
@
click=
"refresh"
class=
"ml-12px"
>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-icon><IEpSearch
/></el-icon>
<el-button
@
click=
"reset"
>
重置
</el-button>
搜索
</div>
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<ExportExcelBtn
:api=
"exportShopItemList"
:searchParams=
"searchParams"
:columns=
"columns"
fileName=
"商品分发数据"
/>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -74,7 +81,9 @@
...
@@ -74,7 +81,9 @@
<el-table-column
prop=
"issueTime"
label=
"发放时间"
min-width=
"200"
>
<el-table-column
prop=
"issueTime"
label=
"发放时间"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
{{
dayjs
(
row
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
{{
row
.
issueTime
?
dayjs
(
row
.
issueTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
:
'未发货'
}}
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
prop=
"status"
label=
"发放状态"
min-width=
"200"
>
<el-table-column
prop=
"status"
label=
"发放状态"
min-width=
"200"
>
...
@@ -82,7 +91,7 @@
...
@@ -82,7 +91,7 @@
{{
row
.
status
===
0
?
'待发货'
:
row
.
status
===
1
?
'已发货'
:
'已取消'
}}
{{
row
.
status
===
0
?
'待发货'
:
row
.
status
===
1
?
'已发货'
:
'已取消'
}}
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
prop=
"
showName
"
label=
"发放人备注"
min-width=
"200"
/>
<el-table-column
prop=
"
memo
"
label=
"发放人备注"
min-width=
"200"
/>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-button
v-if=
"row.status === 0"
type=
"primary"
link
@
click=
"handleIssue(row)"
>
<el-button
v-if=
"row.status === 0"
type=
"primary"
link
@
click=
"handleIssue(row)"
>
...
@@ -140,7 +149,7 @@
...
@@ -140,7 +149,7 @@
<
template
#
footer
>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
<el-icon
class=
"btn-icon"
><
IEp
Upload
/></el-icon>
保存
保存
</el-button>
</el-button>
</
template
>
</
template
>
...
@@ -149,21 +158,90 @@
...
@@ -149,21 +158,90 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
addOrUpdateColumn
,
getBackendExchangeList
,
issueProduct
}
from
'@/api/backend'
import
{
addOrUpdateColumn
,
getBackendExchangeList
,
issueProduct
,
exportShopItemList
,
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendColumnListItemDto
,
AddOrUpdateColumnDto
}
from
'@/api/backend'
import
type
{
BackendColumnListItemDto
,
AddOrUpdateColumnDto
,
BackendShopItemDto
,
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
import
dayjs
from
'dayjs'
import
{
ArticleTypeEnum
}
from
'@/constants'
import
ExportExcelBtn
from
'@/components/common/ExportExcelBtn/index.vue'
import
type
{
ExportColumn
}
from
'@/utils'
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
getBackendExchangeList
,
{
usePageSearch
(
getBackendExchangeList
,
{
defaultParams
:
{
defaultParams
:
{},
type
:
ArticleTypeEnum
.
VIDEO
,
},
})
})
const
columns
:
ExportColumn
<
BackendShopItemDto
>
[]
=
[
{
title
:
'商品名称'
,
key
:
'itemName'
,
},
{
title
:
'图片'
,
key
:
'imageUrl'
,
},
{
title
:
'来源'
,
key
:
'source'
,
formatter
:
(
value
)
=>
{
return
value
===
1
?
'商城'
:
value
===
2
?
'大转盘'
:
'每日抽奖'
},
},
{
title
:
'兑换数量'
,
key
:
'num'
,
},
{
title
:
'兑换时间'
,
key
:
'createTime'
,
formatter
:
(
value
)
=>
{
return
dayjs
((
value
as
number
)
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
},
},
{
title
:
'兑换人'
,
key
:
'userName'
,
},
{
title
:
'发放人'
,
key
:
'issuerName'
,
},
{
title
:
'发放备注'
,
key
:
'memo'
,
},
{
title
:
'发放时间'
,
key
:
'issueTime'
,
formatter
:
(
value
)
=>
{
return
value
?
dayjs
((
value
as
number
)
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
:
'未发货'
},
},
{
title
:
'发放状态'
,
key
:
'status'
,
formatter
:
(
value
)
=>
{
return
value
===
0
?
'待发货'
:
value
===
1
?
'已发货'
:
'已取消'
},
},
{
title
:
'发放人备注'
,
key
:
'memo'
,
},
]
// 对话框
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogVisible
=
ref
(
false
)
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
...
@@ -261,7 +339,8 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
...
@@ -261,7 +339,8 @@ const handleSelectionChange = (selection: BackendColumnListItemDto[]) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/goodsManage/index.vue
deleted
100644 → 0
View file @
2a7fbb51
<
template
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
v-model=
"searchParams.name"
placeholder=
"请输入商品名称"
class=
"w-200px"
></el-input>
<el-select
v-model=
"searchParams.itemType"
placeholder=
"请选择商品类型"
class=
"search-select"
clearable
>
<el-option
label=
"实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
<el-option
label=
"虚拟"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
</el-select>
<el-select
v-model=
"searchParams.region"
placeholder=
"请选择上架地区"
class=
"search-select"
clearable
>
<el-option
v-for=
"item in regionListOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
<el-select
v-model=
"searchParams.enable"
placeholder=
"是否展示在前台"
class=
"search-select"
clearable
>
<el-option
label=
"是"
:value=
"BooleanFlag.YES"
/>
<el-option
label=
"否"
:value=
"BooleanFlag.NO"
/>
</el-select>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
</div>
<div
class=
"flex justify-end"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增
</el-button>
</div>
</div>
<!-- 表格区域 -->
<div
class=
"table-section"
>
<!-- 表格 -->
<div
class=
"table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"list"
height=
"100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
>
</el-table-column>
<el-table-column
prop=
"sortOrder"
label=
"商品排序"
min-width=
"200"
/>
<el-table-column
prop=
"name"
label=
"商品名称"
min-width=
"200"
/>
<el-table-column
prop=
"itemTypeName"
label=
"商品类型"
min-width=
"200"
/>
<el-table-column
prop=
"description"
label=
"商品描述"
min-width=
"200"
/>
<el-table-column
prop=
"imageUrl"
label=
"图片"
width=
"300"
>
<template
#
default=
"
{ row }">
<el-image
:preview-teleported=
"true"
:src=
"row.imageUrl"
class=
"w-20 h-20 object-cover"
:preview-src-list=
"[row.imageUrl]"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"region"
label=
"上架地区"
min-width=
"200"
>
</el-table-column>
<el-table-column
prop=
"stock"
label=
"库存数量"
min-width=
"200"
>
</el-table-column>
<el-table-column
prop=
"price"
label=
"兑换所需YA币"
min-width=
"200"
>
</el-table-column>
<el-table-column
prop=
"showName"
label=
"创建人"
min-width=
"200"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
{{
dayjs
(
row
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"enable"
label=
"是否展示在前台"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<el-switch
:active-value=
"1"
:inactive-value=
"0"
active-text=
"是"
inactive-text=
"否"
:model-value=
"row.enable"
@
change=
"handleEnableChange(row)"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"primary"
link
@
click=
"handleEdit(row)"
>
编辑
</el-button>
<el-button
type=
"danger"
link
@
click=
"handleDelete(row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div
class=
"pagination-wrapper"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
:page-sizes=
"[10, 20, 30]"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
/>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"500px"
:close-on-click-modal=
"false"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
label-width=
"auto"
>
<el-form-item
label=
"商品名称"
prop=
"name"
>
<el-input
v-model=
"form.name"
placeholder=
"请输入商品名称"
/>
</el-form-item>
<el-form-item
label=
"商品类型"
prop=
"itemType"
>
<el-select
v-model=
"form.itemType"
placeholder=
"请选择商品类型"
>
<el-option
label=
"实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
<el-option
label=
"虚拟"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"商品描述"
prop=
"description"
>
<el-input
type=
"textarea"
v-model=
"form.description"
placeholder=
"请输入商品描述"
/>
</el-form-item>
<el-form-item
label=
"图片"
prop=
"imageUrl"
>
<UploadFile
v-model=
"form.imageUrl"
:limit=
"1"
/>
</el-form-item>
<el-form-item
label=
"上架地区"
prop=
"region"
>
<el-select
v-model=
"form.region"
placeholder=
"请选择上架地区"
>
<el-option
v-for=
"item in regionListOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"兑换所需YA币"
prop=
"price"
>
<el-input-number
v-model=
"form.price"
placeholder=
"请输入"
:min=
"0"
/>
</el-form-item>
<el-form-item
label=
"库存数量"
prop=
"stock"
>
<el-input-number
v-model=
"form.stock"
placeholder=
"请输入"
:min=
"0"
/>
</el-form-item>
<el-form-item
label=
"排序"
prop=
"sortOrder"
>
<el-input-number
v-model=
"form.sortOrder"
placeholder=
"请输入"
:min=
"0"
/>
</el-form-item>
<el-form-item
label=
"是否展示在前台"
prop=
"enable"
>
<el-switch
v-model=
"form.enable"
:active-value=
"1"
:inactive-value=
"0"
active-text=
"是"
inactive-text=
"否"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
保存
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
getShopItemList
,
addOrUpdateShopItem
,
deleteShopItem
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendColumnListItemDto
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
import
{
BooleanFlag
,
ShopGoodsTypeEnum
,
regionListOptions
}
from
'@/constants'
import
UploadFile
from
'@/components/common/UploadFile/index.vue'
import
type
{
BackendShopItemDto
}
from
'@/api/backend'
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
getShopItemList
)
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
const
formRef
=
ref
<
FormInstance
>
()
// 表单数据
const
[
form
,
resetForm
]
=
useResetData
<
BackendShopItemDto
>
({
id
:
undefined
,
sort
:
0
,
enable
:
1
,
imageUrl
:
''
,
itemType
:
ShopGoodsTypeEnum
.
REAL_GOODS
,
name
:
''
,
price
:
0
,
region
:
''
,
stock
:
0
,
sortOrder
:
0
,
description
:
''
,
})
// 表单验证规则
const
formRules
:
FormRules
=
{
title
:
[{
required
:
true
,
message
:
'请输入标题'
,
trigger
:
'blur'
}],
color
:
[{
required
:
true
,
message
:
'请选择颜色'
,
trigger
:
'change'
}],
sort
:
[{
required
:
true
,
message
:
'请输入排序'
,
trigger
:
'blur'
}],
}
// 新增
const
handleAdd
=
()
=>
{
resetForm
()
dialogVisible
.
value
=
true
}
// 编辑
const
handleEdit
=
(
row
:
BackendColumnListItemDto
)
=>
{
resetForm
()
form
.
value
=
{
...
row
,
}
dialogVisible
.
value
=
true
}
// 删除
const
handleDelete
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除商品"
${
row
.
name
}
"吗?`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
await
deleteShopItem
(
row
.
id
)
refresh
()
ElMessage
.
success
(
'删除成功'
)
refresh
()
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
'删除失败'
)
}
}
}
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
try
{
await
formRef
.
value
.
validate
()
if
(
form
.
value
.
id
)
{
await
addOrUpdateShopItem
(
form
.
value
)
}
else
{
await
addOrUpdateShopItem
(
form
.
value
)
}
ElMessage
.
success
(
form
.
value
.
id
?
'编辑成功'
:
'新增成功'
)
dialogVisible
.
value
=
false
if
(
form
.
value
.
id
)
{
search
()
}
else
{
refresh
()
}
}
catch
(
error
)
{
console
.
error
(
'表单验证失败:'
,
error
)
}
}
const
selectedRows
=
ref
<
BackendColumnListItemDto
[]
>
([])
// 选择
const
handleSelectionChange
=
(
selection
:
BackendColumnListItemDto
[])
=>
{
selectedRows
.
value
=
selection
}
const
handleEnableChange
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
console
.
log
(
row
)
await
addOrUpdateShopItem
({
id
:
row
.
id
,
enable
:
row
.
enable
===
BooleanFlag
.
YES
?
BooleanFlag
.
NO
:
BooleanFlag
.
YES
,
})
ElMessage
.
success
(
'修改成功'
)
refresh
()
}
</
script
>
<
style
scoped
lang=
"scss"
>
.official-tag-page
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
//
搜索区域
.search-section
{
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
gap
:
12px
;
flex-shrink
:
0
;
.search-select
{
width
:
200px
;
}
}
//
表格区域
.table-section
{
flex
:
1
;
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-direction
:
column
;
min-height
:
0
;
}
.table-wrapper
{
flex
:
1
;
min-height
:
0
;
.color-cell
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
.color-block
{
width
:
100%
;
height
:
36px
;
border-radius
:
4px
;
border
:
1px
solid
#e5e7eb
;
flex
:
1
;
}
.color-text
{
color
:
#fff
;
font-size
:
14px
;
font-weight
:
500
;
position
:
absolute
;
left
:
50%
;
transform
:
translateX
(
-50%
);
text-shadow
:
0
0
3px
rgba
(
0
,
0
,
0
,
0.5
);
}
}
}
.pagination-wrapper
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
16px
;
flex-shrink
:
0
;
}
//
对话框内的颜色显示
.color-value
{
margin-left
:
12px
;
color
:
#606266
;
font-family
:
monospace
;
}
.btn-icon
{
margin-right
:
4px
;
}
</
style
>
src/views/backend/index.vue
View file @
ea5de822
...
@@ -21,8 +21,8 @@ export default defineComponent(() => {
...
@@ -21,8 +21,8 @@ export default defineComponent(() => {
// { path: '/backend/videoSettings', title: '视频——栏目管理' },
// { path: '/backend/videoSettings', title: '视频——栏目管理' },
// { path: '/backend/videoManage', title: '视频管理' },
// { path: '/backend/videoManage', title: '视频管理' },
{
path
:
'/backend/caseManage'
,
title
:
'YAYA案例库管理'
},
{
path
:
'/backend/caseManage'
,
title
:
'YAYA案例库管理'
},
{
path
:
'/backend/goodsManage'
,
title
:
'积分商城——商品配置'
},
//
{ path: '/backend/goodsManage', title: '积分商城——商品配置' },
{
path
:
'/backend/goodsDistribution'
,
title
:
'
积分商城——
商品分发'
},
{
path
:
'/backend/goodsDistribution'
,
title
:
'商品分发'
},
// 内容管理
// 内容管理
{
{
path
:
'/backend/contentsMenu'
,
path
:
'/backend/contentsMenu'
,
...
...
src/views/backend/manager/index.vue
deleted
100644 → 0
View file @
2a7fbb51
<!-- views/backend/topic-target/index.vue -->
<
template
>
<div
class=
"topic-target-page"
>
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<el-input
v-model=
"searchForm.name"
placeholder=
"请输入栏目板块"
class=
"search-input"
clearable
/>
<el-select
v-model=
"searchForm.status"
placeholder=
"请选择"
class=
"search-select"
clearable
>
<el-option
label=
"全部"
value=
""
/>
<el-option
label=
"已发布"
value=
"published"
/>
<el-option
label=
"未发布"
value=
"unpublished"
/>
</el-select>
<el-button
type=
"primary"
@
click=
"handleSearch"
>
搜索
</el-button>
<el-button
@
click=
"handleReset"
>
重置
</el-button>
</div>
<!-- 表格区域 -->
<div
class=
"table-section"
>
<!-- 操作按钮 -->
<div
class=
"action-bar"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
新增
</el-button>
<el-button
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
<!-- 表格 -->
<div
class=
"table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"tableData"
height=
"100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
prop=
"order"
label=
"栏目顺序"
width=
"100"
/>
<el-table-column
prop=
"name"
label=
"栏目名称"
min-width=
"150"
/>
<el-table-column
prop=
"color"
label=
"颜色"
width=
"150"
>
<template
#
default=
"
{ row }">
<div
class=
"color-cell"
>
<div
class=
"color-block"
:style=
"
{ backgroundColor: row.color }" />
<span>
{{
row
.
color
}}
</span>
</div>
</
template
>
</el-table-column>
<el-table-column
prop=
"count"
label=
"栏目标签数量"
width=
"120"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
width=
"180"
/>
<el-table-column
prop=
"creator"
label=
"创建人"
width=
"180"
/>
<el-table-column
label=
"状态"
width=
"100"
>
<
template
#
default=
"{ row }"
>
<el-switch
v-model=
"row.published"
active-text=
"发布"
inactive-text=
"隐藏"
@
change=
"handleStatusChange(row)"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"primary"
link
@
click=
"handleEdit(row)"
>
编辑
</el-button>
<el-button
type=
"danger"
link
@
click=
"handleDelete(row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div
class=
"pagination-wrapper"
>
<el-pagination
v-model:current-page=
"pagination.page"
v-model:page-size=
"pagination.size"
:total=
"pagination.total"
:page-sizes=
"[20, 50, 100]"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"handleSizeChange"
@
current-change=
"handlePageChange"
/>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"600px"
>
<el-form
ref=
"formRef"
:model=
"formData"
:rules=
"formRules"
label-width=
"100px"
>
<el-form-item
label=
"栏目名称"
prop=
"name"
>
<el-input
v-model=
"formData.name"
placeholder=
"请输入栏目名称"
/>
</el-form-item>
<el-form-item
label=
"颜色"
prop=
"color"
>
<el-color-picker
v-model=
"formData.color"
/>
</el-form-item>
<el-form-item
label=
"顺序"
prop=
"order"
>
<el-input-number
v-model=
"formData.order"
:min=
"0"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
确定
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
computed
,
onMounted
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
,
type
FormInstance
,
type
FormRules
}
from
'element-plus'
interface
SearchForm
{
name
:
string
status
:
string
}
interface
TableRow
{
id
:
number
order
:
number
name
:
string
color
:
string
count
:
number
createTime
:
string
creator
:
string
published
:
boolean
}
interface
FormData
{
id
?:
number
name
:
string
color
:
string
order
:
number
}
interface
Pagination
{
page
:
number
size
:
number
total
:
number
}
// 搜索表单
const
searchForm
=
reactive
<
SearchForm
>
({
name
:
''
,
status
:
''
,
})
// 表格数据
const
loading
=
ref
(
false
)
const
tableData
=
ref
<
TableRow
[]
>
([])
const
selectedRows
=
ref
<
TableRow
[]
>
([])
// 分页
const
pagination
=
reactive
<
Pagination
>
({
page
:
1
,
size
:
20
,
total
:
0
,
})
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogType
=
ref
<
'add'
|
'edit'
>
(
'add'
)
const
formRef
=
ref
<
FormInstance
>
()
const
formData
=
reactive
<
FormData
>
({
name
:
''
,
color
:
'#88FFCB'
,
order
:
0
,
})
const
dialogTitle
=
computed
(()
=>
{
return
dialogType
.
value
===
'add'
?
'新增栏目'
:
'编辑栏目'
})
const
formRules
:
FormRules
=
{
name
:
[{
required
:
true
,
message
:
'请输入栏目名称'
,
trigger
:
'blur'
}],
color
:
[{
required
:
true
,
message
:
'请选择颜色'
,
trigger
:
'change'
}],
order
:
[{
required
:
true
,
message
:
'请输入顺序'
,
trigger
:
'blur'
}],
}
// 搜索
const
handleSearch
=
()
=>
{
pagination
.
page
=
1
fetchData
()
}
// 重置
const
handleReset
=
()
=>
{
searchForm
.
name
=
''
searchForm
.
status
=
''
handleSearch
()
}
// 新增
const
handleAdd
=
()
=>
{
dialogType
.
value
=
'add'
Object
.
assign
(
formData
,
{
name
:
''
,
color
:
'#88FFCB'
,
order
:
0
,
})
dialogVisible
.
value
=
true
}
// 编辑
const
handleEdit
=
(
row
:
TableRow
)
=>
{
dialogType
.
value
=
'edit'
Object
.
assign
(
formData
,
{
id
:
row
.
id
,
name
:
row
.
name
,
color
:
row
.
color
,
order
:
row
.
order
,
})
dialogVisible
.
value
=
true
}
// 删除
const
handleDelete
=
async
(
row
:
TableRow
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
'确定要删除该栏目吗?'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
// TODO: 调用删除接口
ElMessage
.
success
(
'删除成功'
)
fetchData
()
}
catch
{
// 取消删除
}
}
// 批量删除
const
handleBatchDelete
=
async
()
=>
{
if
(
selectedRows
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请选择要删除的数据'
)
return
}
try
{
await
ElMessageBox
.
confirm
(
`确定要删除选中的
${
selectedRows
.
value
.
length
}
条数据吗?`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
// TODO: 调用批量删除接口
ElMessage
.
success
(
'删除成功'
)
fetchData
()
}
catch
{
// 取消删除
}
}
// 批量发布/隐藏
const
handleBatchPublish
=
()
=>
{
if
(
selectedRows
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请选择要操作的数据'
)
return
}
// TODO: 调用批量发布接口
ElMessage
.
success
(
'操作成功'
)
fetchData
()
}
// 状态切换
const
handleStatusChange
=
(
row
:
TableRow
)
=>
{
// TODO: 调用状态更新接口
ElMessage
.
success
(
row
.
published
?
'已发布'
:
'已隐藏'
)
}
// 表格选择
const
handleSelectionChange
=
(
rows
:
TableRow
[])
=>
{
selectedRows
.
value
=
rows
}
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
await
formRef
.
value
.
validate
((
valid
)
=>
{
if
(
valid
)
{
// TODO: 调用新增/编辑接口
ElMessage
.
success
(
dialogType
.
value
===
'add'
?
'新增成功'
:
'编辑成功'
)
dialogVisible
.
value
=
false
fetchData
()
}
})
}
// 分页变化
const
handlePageChange
=
(
page
:
number
)
=>
{
pagination
.
page
=
page
fetchData
()
}
const
handleSizeChange
=
(
size
:
number
)
=>
{
pagination
.
size
=
size
pagination
.
page
=
1
fetchData
()
}
// 获取数据
const
fetchData
=
async
()
=>
{
loading
.
value
=
true
try
{
// TODO: 调用接口获取数据
// 模拟数据
tableData
.
value
=
[
{
id
:
123
,
order
:
123
,
name
:
'专栏标签5'
,
color
:
'#88FFCB'
,
count
:
1
,
createTime
:
'2025-11-20 14:15:07'
,
creator
:
'178126911664085000'
,
published
:
true
,
},
{
id
:
8
,
order
:
8
,
name
:
'专栏标签4'
,
color
:
'#9878FF'
,
count
:
1
,
createTime
:
'2025-11-20 14:14:49'
,
creator
:
'178126911664085000'
,
published
:
true
,
},
{
id
:
0
,
order
:
0
,
name
:
'专栏标签3'
,
color
:
'#f0fdf4'
,
count
:
4
,
createTime
:
'2025-11-10 18:05:37'
,
creator
:
'178126911664085000'
,
published
:
true
,
},
{
id
:
11
,
order
:
11
,
name
:
'专栏标签2'
,
color
:
'#fdf2f8'
,
count
:
0
,
createTime
:
'2025-11-10 17:46:40'
,
creator
:
'178126911664085000'
,
published
:
true
,
},
{
id
:
3
,
order
:
3
,
name
:
'专栏标签1'
,
color
:
'#eff6ff'
,
count
:
3
,
createTime
:
'2025-11-10 17:46:30'
,
creator
:
'178126911664085000'
,
published
:
true
,
},
]
pagination
.
total
=
5
}
catch
(
error
)
{
ElMessage
.
error
(
'获取数据失败'
)
}
finally
{
loading
.
value
=
false
}
}
onMounted
(()
=>
{
fetchData
()
})
</
script
>
<
style
scoped
lang=
"scss"
>
.topic-target-page
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
//
搜索区域
.search-section
{
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
gap
:
12px
;
flex-shrink
:
0
;
.search-input
{
width
:
240px
;
}
.search-select
{
width
:
160px
;
}
}
//
表格区域
-
占满剩余高度
.table-section
{
flex
:
1
;
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-direction
:
column
;
min-height
:
0
;
//
重要:允许flex子元素收缩
}
.action-bar
{
display
:
flex
;
gap
:
12px
;
margin-bottom
:
16px
;
flex-shrink
:
0
;
}
//
表格包裹器
-
自适应高度
.table-wrapper
{
flex
:
1
;
min-height
:
0
;
//
重要:允许flex子元素收缩
.color-cell
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
.color-block
{
width
:
24px
;
height
:
24px
;
border-radius
:
4px
;
border
:
1px
solid
#e5e7eb
;
}
}
}
.pagination-wrapper
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
16px
;
flex-shrink
:
0
;
}
</
style
>
src/views/backend/settingsMenu/auctionManage/components/auctionRecordDialog.vue
0 → 100644
View file @
ea5de822
<
template
>
<el-dialog
v-model=
"visible"
title=
"竞拍记录"
width=
"50%"
>
<el-table
:data=
"list"
style=
"width: 100%"
>
<el-table-column
prop=
"userName"
label=
"竞拍人"
/>
<el-table-column
prop=
"bidTime"
label=
"竞拍时间"
>
<template
#
default=
"
{ row }">
{{
dayjs
.
unix
(
row
.
bidTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"bidPrice"
label=
"竞拍价格"
>
<
template
#
default=
"{ row }"
>
{{
row
.
bidPrice
}}
YA币
</
template
>
</el-table-column>
</el-table>
<div
class=
"flex justify-end mt-3"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
layout=
"total, sizes, prev, pager, next, jumper"
/>
</div>
</el-dialog>
</template>
<
script
setup
lang=
"ts"
>
import
{
usePageSearch
}
from
'@/hooks'
import
{
getAuctionRecord
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
const
visible
=
ref
(
false
)
const
{
list
,
total
,
goToPage
,
changePageSize
,
searchParams
,
search
}
=
usePageSearch
(
getAuctionRecord
,
{
immediate
:
false
,
},
)
const
open
=
(
id
:
number
)
=>
{
searchParams
.
value
.
id
=
id
search
()
visible
.
value
=
true
}
defineExpose
({
open
,
})
</
script
>
src/views/backend/settingsMenu/auctionManage/index.vue
0 → 100644
View file @
ea5de822
<
template
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<el-input
v-model=
"searchParams.name"
placeholder=
"请输入竞拍名称"
clearable
class=
"w-200px mr-12px"
></el-input>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchShow"
:disabled=
"selectedRows.length === 0"
>
批量修改展示竞拍
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
:disabled=
"selectedRows.length === 0"
>
批量删除
</el-button>
</div>
<!-- 表格区域 -->
<div
class=
"table-section"
>
<!-- 表格 -->
<div
class=
"table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"list"
height=
"100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
>
</el-table-column>
<el-table-column
prop=
"createUserName"
label=
"发布人"
width=
"100"
/>
<el-table-column
prop=
"createdAt"
label=
"发布时间"
width=
"200"
>
<template
#
default=
"
{ row }">
{{
dayjs
(
row
.
createdAt
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"name"
label=
"名称"
width=
"200"
/>
<el-table-column
prop=
"imageUrl"
label=
"图片"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-image
v-if=
"row.imageUrl"
:preview-teleported=
"true"
:src=
"row.imageUrl"
class=
"w-20 h-20 object-cover"
:preview-src-list=
"[row.imageUrl]"
/>
<span
v-else
>
暂无图片
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"description"
label=
"介绍内容"
width=
"200"
:ellipsis=
"true"
:show-overflow-tooltip=
"{
placement: 'top',
popperClass: 'max-w-300',
}"
>
</el-table-column>
<el-table-column
prop=
"quantity"
label=
"数量"
width=
"100"
>
</el-table-column>
<el-table-column
prop=
"specification"
label=
"规格"
width=
"100"
>
</el-table-column>
<el-table-column
prop=
"startingPrice"
label=
"起拍价"
width=
"100"
/>
<el-table-column
prop=
"minIncrement"
label=
"最低加价幅度"
width=
"150"
/>
<el-table-column
prop=
"currentPrice"
label=
"当前出价"
width=
"150"
/>
<el-table-column
prop=
"bidLimit"
label=
"竞拍次数上限"
width=
"150"
/>
<el-table-column
prop=
"startTime"
label=
"竞拍时间"
width=
"320"
>
<
template
#
default=
"{ row }"
>
{{
dayjs
(
row
.
startTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
~
{{
dayjs
(
row
.
endTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"statusDesc"
label=
"展示竞拍"
width=
"100"
>
<
template
#
default=
"{ row }"
>
{{
row
.
isDisplay
===
1
?
'是'
:
'否'
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"showName"
label=
"竞拍状态"
width=
"100"
>
<
template
#
default=
"{ row }"
>
{{
// 未展示的时候不展示竞拍状态
row
.
isDisplay
===
0
?
''
:
auctionStatusListOptions
.
find
((
item
)
=>
item
.
value
===
row
.
status
)?.
label
}}
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"180"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"primary"
link
@
click=
"handleEdit(row)"
>
编辑
</el-button>
<el-button
type=
"primary"
link
@
click=
"handleAuctionRecord(row)"
>
竞拍记录
</el-button>
<el-button
type=
"danger"
link
@
click=
"handleDelete(row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div
class=
"pagination-wrapper"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
:page-sizes=
"[10, 20, 30]"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
/>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"510px"
top=
"5vh"
:close-on-click-modal=
"false"
>
<el-scrollbar
height=
"650px"
class=
"pr-4"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
label-width=
"auto"
>
<el-form-item
label=
"名称"
prop=
"name"
>
<el-input
v-model=
"form.name"
placeholder=
"请输入名称(最多25个字符)"
maxlength=
"25"
/>
</el-form-item>
<el-form-item
label=
"图片"
prop=
"imageUrl"
>
<UploadFile
v-model=
"form.imageUrl"
:limit=
"1"
/>
</el-form-item>
<el-form-item
label=
"介绍内容"
prop=
"description"
>
<el-input
v-model=
"form.description"
type=
"textarea"
placeholder=
"请输入介绍内容"
/>
</el-form-item>
<el-form-item
label=
"数量"
prop=
"quantity"
>
<el-input-number
class=
"w-60%!"
v-model=
"form.quantity"
:min=
"1"
controls-position=
"right"
/>
</el-form-item>
<el-form-item
label=
"规格"
prop=
"specification"
>
<el-input
v-model=
"form.specification"
placeholder=
"请输入规格(最多4个字符)"
maxlength=
"4"
/>
</el-form-item>
<el-form-item
label=
"起拍价"
prop=
"startingPrice"
>
<el-input-number
class=
"w-60%!"
v-model=
"form.startingPrice"
:min=
"1"
controls-position=
"right"
/>
</el-form-item>
<el-form-item
label=
"最低加价幅度"
prop=
"minIncrement"
>
<el-input-number
class=
"w-60%!"
v-model=
"form.minIncrement"
:min=
"1"
controls-position=
"right"
/>
</el-form-item>
<el-form-item
label=
"竞拍次数上限"
prop=
"bidLimit"
>
<el-input-number
class=
"w-60%!"
v-model=
"form.bidLimit"
:min=
"1"
controls-position=
"right"
/>
</el-form-item>
<el-form-item
label=
"竞拍时间"
prop=
"startTime"
>
<el-date-picker
v-model=
"dateRange"
type=
"datetimerange"
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
value-format=
"X"
/>
</el-form-item>
<el-form-item
label=
"展示竞拍"
prop=
"isDisplay"
>
<el-switch
v-model=
"form.isDisplay"
:active-value=
"1"
:inactive-value=
"0"
active-text=
"是"
inactive-text=
"否"
/>
</el-form-item>
</el-form>
</el-scrollbar>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
:loading=
"submitLoading"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
保存
</el-button>
</
template
>
</el-dialog>
<AuctionRecordDialog
ref=
"auctionRecordDialogRef"
/>
</div>
</template>
<
script
setup
lang=
"tsx"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
getBackendAuctionList
,
addOrUpdateAuctionItem
,
deleteAuction
,
batchUpdateShowAuction
,
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendAuctionListItemDto
,
BackendAddOrUpdateAuctionItemDto
}
from
'@/api/backend'
import
{
auctionStatusListOptions
}
from
'@/constants'
import
UploadFile
from
'@/components/common/UploadFile/index.vue'
import
AuctionRecordDialog
from
'./components/auctionRecordDialog.vue'
import
dayjs
from
'dayjs'
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
getBackendAuctionList
)
const
auctionRecordDialogRef
=
ref
<
InstanceType
<
typeof
AuctionRecordDialog
>>
()
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
const
formRef
=
ref
<
FormInstance
>
()
// 表单数据
const
[
form
,
resetForm
]
=
useResetData
<
BackendAddOrUpdateAuctionItemDto
>
({
id
:
undefined
,
imageUrl
:
''
,
name
:
''
,
description
:
''
,
quantity
:
1
,
specification
:
''
,
startingPrice
:
0
,
minIncrement
:
0
,
bidLimit
:
0
,
isDisplay
:
0
,
startTime
:
''
,
endTime
:
''
,
})
// 表单验证规则
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'
}],
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'
}],
}
const
dateRange
=
computed
({
get
()
{
if
(
form
.
value
.
startTime
&&
form
.
value
.
endTime
)
{
return
[
form
.
value
.
startTime
,
form
.
value
.
endTime
]
}
return
[]
},
set
(
value
)
{
if
(
value
)
{
form
.
value
.
startTime
=
value
[
0
]
||
''
form
.
value
.
endTime
=
value
[
1
]
||
''
}
else
{
form
.
value
.
startTime
=
''
form
.
value
.
endTime
=
''
}
},
})
const
submitLoading
=
ref
(
false
)
// 新增
const
handleAdd
=
()
=>
{
resetForm
()
dialogVisible
.
value
=
true
}
// 编辑
const
handleEdit
=
(
row
:
BackendAddOrUpdateAuctionItemDto
)
=>
{
resetForm
()
form
.
value
=
{
...
row
,
}
dialogVisible
.
value
=
true
}
// 删除
const
handleDelete
=
async
(
row
:
BackendAuctionListItemDto
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除竞拍物品"
${
row
.
name
}
"吗?`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
await
deleteAuction
([
row
.
id
])
refresh
()
ElMessage
.
success
(
'删除成功'
)
refresh
()
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
'删除失败'
)
}
}
}
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
try
{
submitLoading
.
value
=
true
await
formRef
.
value
.
validate
()
if
(
form
.
value
.
id
)
{
await
addOrUpdateAuctionItem
(
form
.
value
)
}
else
{
await
addOrUpdateAuctionItem
(
form
.
value
)
}
ElMessage
.
success
(
form
.
value
.
id
?
'编辑成功'
:
'新增成功'
)
dialogVisible
.
value
=
false
if
(
form
.
value
.
id
)
{
search
()
}
else
{
refresh
()
}
}
catch
(
error
)
{
console
.
error
(
'表单验证失败:'
,
error
)
}
finally
{
submitLoading
.
value
=
false
}
}
const
handleBatchShow
=
async
()
=>
{
const
show
=
ref
(
1
)
await
ElMessageBox
({
title
:
'是否展示竞拍'
,
message
:
()
=>
(
<
el
-
radio
-
group
v
-
model
=
{
show
.
value
}
>
<
el
-
radio
value
=
{
1
}
>
是
<
/el-radio
>
<
el
-
radio
value
=
{
0
}
>
否
<
/el-radio
>
<
/el-radio-group
>
),
showCancelButton
:
true
,
async
beforeClose
(
action
,
instance
,
done
)
{
if
(
action
===
'confirm'
)
{
instance
.
confirmButtonLoading
=
true
try
{
await
batchUpdateShowAuction
({
idList
:
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
),
isDisplay
:
show
.
value
,
})
ElMessage
.
success
(
'批量修改展示竞拍成功'
)
refresh
()
done
()
}
catch
(
error
)
{
console
.
error
(
error
)
}
finally
{
instance
.
confirmButtonLoading
=
false
}
}
else
{
done
()
}
},
})
}
const
handleBatchDelete
=
async
()
=>
{
await
ElMessageBox
.
confirm
(
'确定要删除这些竞拍物品吗?'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
await
deleteAuction
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
ElMessage
.
success
(
'删除成功'
)
}
const
selectedRows
=
ref
<
BackendAuctionListItemDto
[]
>
([])
// 选择
const
handleSelectionChange
=
(
selection
:
BackendAuctionListItemDto
[])
=>
{
selectedRows
.
value
=
selection
}
const
handleAuctionRecord
=
async
(
row
:
BackendAuctionListItemDto
)
=>
{
auctionRecordDialogRef
.
value
?.
open
(
row
.
id
)
}
</
script
>
<
style
scoped
lang=
"scss"
>
.official-tag-page
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
//
搜索区域
.search-section
{
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
.search-select
{
width
:
200px
;
}
}
//
表格区域
.table-section
{
flex
:
1
;
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-direction
:
column
;
min-height
:
0
;
}
.table-wrapper
{
flex
:
1
;
min-height
:
0
;
.color-cell
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
.color-block
{
width
:
100%
;
height
:
36px
;
border-radius
:
4px
;
border
:
1px
solid
#e5e7eb
;
flex
:
1
;
}
.color-text
{
color
:
#fff
;
font-size
:
14px
;
font-weight
:
500
;
position
:
absolute
;
left
:
50%
;
transform
:
translateX
(
-50%
);
text-shadow
:
0
0
3px
rgba
(
0
,
0
,
0
,
0.5
);
}
}
}
.pagination-wrapper
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
16px
;
flex-shrink
:
0
;
}
//
对话框内的颜色显示
.color-value
{
margin-left
:
12px
;
color
:
#606266
;
font-family
:
monospace
;
}
.btn-icon
{
margin-right
:
4px
;
}
</
style
>
src/views/backend/settingsMenu/goodsManage/index.vue
View file @
ea5de822
...
@@ -2,54 +2,49 @@
...
@@ -2,54 +2,49 @@
<div
class=
"official-tag-page"
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
v-model=
"searchParams.name"
placeholder=
"请输入商品名称"
class=
"w-200px"
></el-input>
<el-input
v-model=
"searchParams.name"
<el-select
placeholder=
"请输入商品名称"
v-model=
"searchParams.itemType"
class=
"w-200px"
placeholder=
"请选择商品类型"
></el-input>
class=
"search-select mx-12px"
clearable
<el-select
>
v-model=
"searchParams.itemType"
<el-option
label=
"实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
placeholder=
"请选择商品类型"
<el-option
label=
"虚拟"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
class=
"search-select"
</el-select>
clearable
<el-select
>
v-model=
"searchParams.region"
<el-option
label=
"实物"
:value=
"ShopGoodsTypeEnum.REAL_GOODS"
/>
placeholder=
"请选择上架地区"
<el-option
label=
"虚拟"
:value=
"ShopGoodsTypeEnum.VIRTUAL_GOODS"
/>
class=
"search-select"
</el-select>
clearable
<el-select
>
v-model=
"searchParams.region"
<el-option
placeholder=
"请选择上架地区"
v-for=
"item in regionListOptions"
class=
"search-select"
:key=
"item.value"
clearable
:label=
"item.label"
>
:value=
"item.value"
<el-option
/>
v-for=
"item in regionListOptions"
</el-select>
:key=
"item.value"
<el-select
:label=
"item.label"
v-model=
"searchParams.enable"
:value=
"item.value"
placeholder=
"是否展示在前台"
/>
class=
"search-select mx-12px"
</el-select>
clearable
<el-select
>
v-model=
"searchParams.enable"
<el-option
label=
"是"
:value=
"BooleanFlag.YES"
/>
placeholder=
"是否展示在前台"
<el-option
label=
"否"
:value=
"BooleanFlag.NO"
/>
class=
"search-select"
</el-select>
clearable
<el-button
type=
"primary"
@
click=
"refresh"
>
>
<el-icon><IEpSearch
/></el-icon>
<el-option
label=
"是"
:value=
"BooleanFlag.YES"
/>
搜索
<el-option
label=
"否"
:value=
"BooleanFlag.NO"
/>
</el-button>
</el-select>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
</div>
<el-icon><IEpPlus
/></el-icon>
新增
<div
class=
"flex justify-end"
>
</el-button>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增
</el-button>
</div>
</div>
</div>
<!-- 表格区域 -->
<!-- 表格区域 -->
...
@@ -182,7 +177,7 @@
...
@@ -182,7 +177,7 @@
<
template
#
footer
>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
<el-icon
class=
"btn-icon"
><
IEp
Upload
/></el-icon>
保存
保存
</el-button>
</el-button>
</
template
>
</
template
>
...
@@ -191,7 +186,6 @@
...
@@ -191,7 +186,6 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
getShopItemList
,
addOrUpdateShopItem
,
deleteShopItem
}
from
'@/api/backend'
import
{
getShopItemList
,
addOrUpdateShopItem
,
deleteShopItem
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
...
@@ -322,7 +316,8 @@ const handleEnableChange = async (row: BackendColumnListItemDto) => {
...
@@ -322,7 +316,8 @@ const handleEnableChange = async (row: BackendColumnListItemDto) => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
gap
:
12px
0
;
flex-shrink
:
0
;
flex-shrink
:
0
;
.search-select
{
.search-select
{
...
...
src/views/backend/tags/index.vue
View file @
ea5de822
...
@@ -13,12 +13,14 @@
...
@@ -13,12 +13,14 @@
<el-option
label=
"年度主推关键词"
value=
"year_recommend"
/>
<el-option
label=
"年度主推关键词"
value=
"year_recommend"
/>
<el-option
label=
"关联场景"
value=
"related_scenarios"
/>
<el-option
label=
"关联场景"
value=
"related_scenarios"
/>
</el-select>
</el-select>
<el-button
type=
"primary"
@
click=
"refresh"
class=
"ml-12px"
>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-icon><IEpSearch
/></el-icon>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
<el-button
type=
"primary"
class=
"add-btn"
@
click=
"handleAdd"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
<el-icon><
IEp
Plus
/></el-icon>
新增
新增
</el-button>
</el-button>
</div>
</div>
...
@@ -108,7 +110,9 @@
...
@@ -108,7 +110,9 @@
<
template
#
footer
>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
<el-icon
class=
"btn-icon"
><el-icon><IEpUpload
/></el-icon
></el-icon>
保存
保存
</el-button>
</el-button>
</
template
>
</
template
>
...
@@ -117,7 +121,6 @@
...
@@ -117,7 +121,6 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
getTagList
,
addOrUpdateTag
,
deleteTag
}
from
'@/api/backend'
import
{
getTagList
,
addOrUpdateTag
,
deleteTag
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
...
@@ -228,16 +231,12 @@ const handleSubmit = async () => {
...
@@ -228,16 +231,12 @@ const handleSubmit = async () => {
border-radius
:
8px
;
border-radius
:
8px
;
padding
:
20px
;
padding
:
20px
;
display
:
flex
;
display
:
flex
;
gap
:
12px
;
flex-wrap
:
wrap
;
flex-shrink
:
0
;
flex-shrink
:
0
;
gap
:
12px
0
;
.search-select
{
.search-select
{
width
:
200px
;
width
:
200px
;
}
}
.add-btn
{
margin-left
:
auto
;
}
}
}
//
表格区域
//
表格区域
...
...
src/views/backend/videoManage/index.vue
deleted
100644 → 0
View file @
2a7fbb51
<
template
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
class=
"w-200px"
></el-input>
<el-select
v-model=
"searchParams.status"
placeholder=
"请选择发布状态"
class=
"search-select"
clearable
>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
</el-select>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
</div>
<!--
<div
class=
"flex justify-end"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
-->
</div>
<!-- 表格区域 -->
<div
class=
"table-section"
>
<!-- 表格 -->
<div
class=
"table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"list"
height=
"100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
>
</el-table-column>
<el-table-column
prop=
"title"
label=
"视频标题"
min-width=
"200"
/>
<el-table-column
prop=
"content"
label=
"视频简介"
min-width=
"200"
/>
<el-table-column
prop=
"faceUrl"
label=
"视频封面"
width=
"300"
>
<template
#
default=
"
{ row }">
<el-image
:preview-teleported=
"true"
:src=
"row.faceUrl"
class=
"w-20 h-20 object-cover"
:preview-src-list=
"[row.faceUrl]"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"videoUrl"
label=
"视频地址"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<el-link
type=
"primary"
:href=
"row.videoUrl"
target=
"_blank"
:underline=
"false"
>
{{
row
.
videoUrl
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
prop=
"releaseStatus"
label=
"标签"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<el-tag
v-for=
"tag in row.tagNameList"
:key=
"tag.tagId"
type=
"primary"
class=
"mr-2! mb-2!"
>
{{
tag
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"是否置顶"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<el-switch
:model-value=
"row.isRecommend"
:active-value=
"1"
:inactive-value=
"0"
@
change=
"handleIsRecommendChange(row)"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"showName"
label=
"创建人"
min-width=
"200"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
{{
dayjs
(
row
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<!-- <el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column> -->
</el-table>
</div>
<!-- 分页 -->
<div
class=
"pagination-wrapper"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
:page-sizes=
"[10, 20, 30]"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
/>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"500px"
:close-on-click-modal=
"false"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
label-width=
"80px"
>
<el-form-item
label=
"标题"
prop=
"title"
>
<el-input
v-model=
"form.title"
placeholder=
"请输入标题"
/>
</el-form-item>
<el-form-item
label=
"颜色"
prop=
"color"
>
<el-color-picker
v-model=
"form.color"
/>
<span
class=
"color-value"
>
{{ form.color }}
</span>
</el-form-item>
<el-form-item
label=
"排序"
prop=
"sort"
>
<el-input-number
v-model=
"form.sort"
:min=
"0"
:max=
"100"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
保存
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
addOrUpdateColumn
,
deleteColumn
,
hideColumn
}
from
'@/api/backend'
import
{
getArticleList
,
updateArticleRecommendAndSort
}
from
'@/api'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendColumnListItemDto
,
AddOrUpdateColumnDto
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
import
{
ArticleTypeEnum
}
from
'@/constants'
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
getArticleList
,
{
defaultParams
:
{
type
:
ArticleTypeEnum
.
VIDEO
,
},
})
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
const
formRef
=
ref
<
FormInstance
>
()
// 表单数据
const
[
form
,
resetForm
]
=
useResetData
<
AddOrUpdateColumnDto
>
({
title
:
''
,
color
:
'#000000'
,
id
:
undefined
,
sort
:
0
,
type
:
'column'
,
})
// 表单验证规则
const
formRules
:
FormRules
=
{
title
:
[{
required
:
true
,
message
:
'请输入标题'
,
trigger
:
'blur'
}],
color
:
[{
required
:
true
,
message
:
'请选择颜色'
,
trigger
:
'change'
}],
sort
:
[{
required
:
true
,
message
:
'请输入排序'
,
trigger
:
'blur'
}],
}
// 新增
const
handleAdd
=
()
=>
{
resetForm
()
dialogVisible
.
value
=
true
}
// 编辑
const
handleEdit
=
(
row
:
BackendColumnListItemDto
)
=>
{
resetForm
()
form
.
value
=
{
title
:
row
.
title
,
color
:
row
.
color
,
id
:
row
.
id
,
sort
:
row
.
sort
,
type
:
'column'
,
}
dialogVisible
.
value
=
true
}
// 是否置顶改变
const
handleIsRecommendChange
=
async
(
row
:
ArticleItemDto
)
=>
{
await
updateArticleRecommendAndSort
(
row
.
id
)
ElMessage
.
success
(
'修改成功'
)
refresh
()
}
// 删除
const
handleDelete
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除标签"
${
row
.
title
}
"吗?`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
await
deleteColumn
([
row
.
id
])
ElMessage
.
success
(
'删除成功'
)
refresh
()
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
'删除失败'
)
}
}
}
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
try
{
await
formRef
.
value
.
validate
()
if
(
form
.
value
.
id
)
{
await
addOrUpdateColumn
(
form
.
value
)
}
else
{
await
addOrUpdateColumn
(
form
.
value
)
}
ElMessage
.
success
(
form
.
value
.
id
?
'编辑成功'
:
'新增成功'
)
dialogVisible
.
value
=
false
if
(
form
.
value
.
id
)
{
search
()
}
else
{
refresh
()
}
}
catch
(
error
)
{
console
.
error
(
'表单验证失败:'
,
error
)
}
}
const
selectedRows
=
ref
<
BackendColumnListItemDto
[]
>
([])
// 选择
const
handleSelectionChange
=
(
selection
:
BackendColumnListItemDto
[])
=>
{
selectedRows
.
value
=
selection
}
// 批量发布/隐藏
const
handleBatchPublish
=
async
()
=>
{
await
hideColumn
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
selectedRows
.
value
=
[]
ElMessage
.
success
(
'发布/隐藏成功'
)
}
// 批量删除
const
handleBatchDelete
=
async
()
=>
{
await
deleteColumn
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
selectedRows
.
value
=
[]
ElMessage
.
success
(
'删除成功'
)
}
</
script
>
<
style
scoped
lang=
"scss"
>
.official-tag-page
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
//
搜索区域
.search-section
{
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
gap
:
12px
;
flex-shrink
:
0
;
.search-select
{
width
:
200px
;
}
}
//
表格区域
.table-section
{
flex
:
1
;
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-direction
:
column
;
min-height
:
0
;
}
.table-wrapper
{
flex
:
1
;
min-height
:
0
;
.color-cell
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
.color-block
{
width
:
100%
;
height
:
36px
;
border-radius
:
4px
;
border
:
1px
solid
#e5e7eb
;
flex
:
1
;
}
.color-text
{
color
:
#fff
;
font-size
:
14px
;
font-weight
:
500
;
position
:
absolute
;
left
:
50%
;
transform
:
translateX
(
-50%
);
text-shadow
:
0
0
3px
rgba
(
0
,
0
,
0
,
0.5
);
}
}
}
.pagination-wrapper
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
16px
;
flex-shrink
:
0
;
}
//
对话框内的颜色显示
.color-value
{
margin-left
:
12px
;
color
:
#606266
;
font-family
:
monospace
;
}
.btn-icon
{
margin-right
:
4px
;
}
</
style
>
src/views/backend/videoSettings/index.vue
deleted
100644 → 0
View file @
2a7fbb51
<
template
>
<div
class=
"official-tag-page"
>
<!-- 搜索栏 -->
<div
class=
"search-section"
>
<div
class=
"flex-1 flex gap-2"
>
<el-input
v-model=
"searchParams.title"
placeholder=
"请输入栏目标题"
class=
"w-200px"
clearable
></el-input>
<el-select
v-model=
"searchParams.status"
placeholder=
"请选择发布状态"
class=
"search-select"
clearable
>
<el-option
label=
"发布"
:value=
"1"
/>
<el-option
label=
"隐藏"
:value=
"0"
/>
</el-select>
<el-button
type=
"primary"
:icon=
"Search"
@
click=
"refresh"
>
搜索
</el-button>
<el-button
@
click=
"reset"
>
重置
</el-button>
</div>
<div
class=
"flex justify-end"
>
<el-button
type=
"primary"
@
click=
"handleAdd"
>
<el-icon><Plus
/></el-icon>
新增
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchPublish"
>
批量发布/隐藏
</el-button>
<el-button
type=
"danger"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
</div>
<!-- 表格区域 -->
<div
class=
"table-section"
>
<!-- 表格 -->
<div
class=
"table-wrapper"
>
<el-table
v-loading=
"loading"
:data=
"list"
height=
"100%"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
>
</el-table-column>
<el-table-column
prop=
"sort"
label=
"栏目顺序"
width=
"180"
>
</el-table-column>
<el-table-column
prop=
"title"
label=
"栏目名称"
min-width=
"200"
/>
<el-table-column
prop=
"postCount"
label=
"栏目帖子数量"
min-width=
"200"
/>
<el-table-column
prop=
"color"
label=
"颜色"
width=
"300"
>
<template
#
default=
"
{ row }">
<div
class=
"color-cell"
>
<div
class=
"color-block"
:style=
"
{ backgroundColor: row.color }" />
<span
class=
"color-text"
>
{{
row
.
color
}}
</span>
</div>
</
template
>
</el-table-column>
<el-table-column
prop=
"createUserId"
label=
"创建人"
min-width=
"200"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
{{
dayjs
(
row
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"状态"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<el-switch
:model-value=
"row.status"
:active-value=
"1"
:inactive-value=
"0"
@
change=
"handleStatusChange(row)"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"primary"
link
@
click=
"handleEdit(row)"
>
编辑
</el-button>
<el-button
type=
"danger"
link
@
click=
"handleDelete(row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
<!-- 分页 -->
<div
class=
"pagination-wrapper"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"total"
:page-sizes=
"[10, 20, 30]"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
/>
</div>
</div>
<!-- 新增/编辑对话框 -->
<el-dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"500px"
:close-on-click-modal=
"false"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"formRules"
label-width=
"80px"
>
<el-form-item
label=
"标题"
prop=
"title"
>
<el-input
v-model=
"form.title"
placeholder=
"请输入标题"
/>
</el-form-item>
<el-form-item
label=
"颜色"
prop=
"color"
>
<el-color-picker
v-model=
"form.color"
/>
<span
class=
"color-value"
>
{{ form.color }}
</span>
</el-form-item>
<el-form-item
label=
"排序"
prop=
"sort"
>
<el-input-number
v-model=
"form.sort"
:min=
"0"
:max=
"100"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"dialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
<el-icon
class=
"btn-icon"
><Upload
/></el-icon>
保存
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
Search
,
Plus
,
Upload
}
from
'@element-plus/icons-vue'
import
{
usePageSearch
,
useResetData
}
from
'@/hooks'
import
{
listOfCultureColumn
,
addOrUpdateColumn
,
deleteColumn
,
hideColumn
}
from
'@/api/backend'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BackendColumnListItemDto
,
AddOrUpdateColumnDto
}
from
'@/api/backend'
import
dayjs
from
'dayjs'
const
{
loading
,
list
,
total
,
reset
,
goToPage
,
changePageSize
,
refresh
,
searchParams
,
search
}
=
usePageSearch
(
listOfCultureColumn
,
{
defaultParams
:
{
type
:
'video'
,
},
})
// 对话框
const
dialogVisible
=
ref
(
false
)
const
dialogTitle
=
computed
(()
=>
(
form
.
value
.
id
?
'编辑标签'
:
'新增标签'
))
const
formRef
=
ref
<
FormInstance
>
()
// 表单数据
const
[
form
,
resetForm
]
=
useResetData
<
AddOrUpdateColumnDto
>
({
title
:
''
,
color
:
'#000000'
,
id
:
undefined
,
sort
:
0
,
type
:
'video'
,
})
// 表单验证规则
const
formRules
:
FormRules
=
{
title
:
[{
required
:
true
,
message
:
'请输入标题'
,
trigger
:
'blur'
}],
color
:
[{
required
:
true
,
message
:
'请选择颜色'
,
trigger
:
'change'
}],
sort
:
[{
required
:
true
,
message
:
'请输入排序'
,
trigger
:
'blur'
}],
}
// 新增
const
handleAdd
=
()
=>
{
resetForm
()
dialogVisible
.
value
=
true
}
// 编辑
const
handleEdit
=
(
row
:
BackendColumnListItemDto
)
=>
{
resetForm
()
form
.
value
=
{
title
:
row
.
title
,
color
:
row
.
color
,
id
:
row
.
id
,
sort
:
row
.
sort
,
type
:
'video'
,
}
dialogVisible
.
value
=
true
}
// 状态改变
const
handleStatusChange
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
await
hideColumn
([
row
.
id
])
refresh
()
}
// 删除
const
handleDelete
=
async
(
row
:
BackendColumnListItemDto
)
=>
{
try
{
await
ElMessageBox
.
confirm
(
`确定要删除标签"
${
row
.
title
}
"吗?`
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
})
await
deleteColumn
([
row
.
id
])
ElMessage
.
success
(
'删除成功'
)
refresh
()
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
ElMessage
.
error
(
'删除失败'
)
}
}
}
// 提交表单
const
handleSubmit
=
async
()
=>
{
if
(
!
formRef
.
value
)
return
try
{
await
formRef
.
value
.
validate
()
if
(
form
.
value
.
id
)
{
await
addOrUpdateColumn
(
form
.
value
)
}
else
{
await
addOrUpdateColumn
(
form
.
value
)
}
ElMessage
.
success
(
form
.
value
.
id
?
'编辑成功'
:
'新增成功'
)
dialogVisible
.
value
=
false
if
(
form
.
value
.
id
)
{
search
()
}
else
{
refresh
()
}
}
catch
(
error
)
{
console
.
error
(
'表单验证失败:'
,
error
)
}
}
const
selectedRows
=
ref
<
BackendColumnListItemDto
[]
>
([])
// 选择
const
handleSelectionChange
=
(
selection
:
BackendColumnListItemDto
[])
=>
{
selectedRows
.
value
=
selection
}
// 批量发布/隐藏
const
handleBatchPublish
=
async
()
=>
{
await
hideColumn
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
selectedRows
.
value
=
[]
ElMessage
.
success
(
'发布/隐藏成功'
)
}
// 批量删除
const
handleBatchDelete
=
async
()
=>
{
await
deleteColumn
(
selectedRows
.
value
.
map
((
item
)
=>
item
.
id
))
refresh
()
selectedRows
.
value
=
[]
ElMessage
.
success
(
'删除成功'
)
}
</
script
>
<
style
scoped
lang=
"scss"
>
.official-tag-page
{
height
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
//
搜索区域
.search-section
{
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
gap
:
12px
;
flex-shrink
:
0
;
.search-select
{
width
:
200px
;
}
}
//
表格区域
.table-section
{
flex
:
1
;
background
:
#fff
;
border-radius
:
8px
;
padding
:
20px
;
display
:
flex
;
flex-direction
:
column
;
min-height
:
0
;
}
.table-wrapper
{
flex
:
1
;
min-height
:
0
;
.color-cell
{
display
:
flex
;
align-items
:
center
;
gap
:
12px
;
.color-block
{
width
:
100%
;
height
:
36px
;
border-radius
:
4px
;
border
:
1px
solid
#e5e7eb
;
flex
:
1
;
}
.color-text
{
color
:
#fff
;
font-size
:
14px
;
font-weight
:
500
;
position
:
absolute
;
left
:
50%
;
transform
:
translateX
(
-50%
);
text-shadow
:
0
0
3px
rgba
(
0
,
0
,
0
,
0.5
);
}
}
}
.pagination-wrapper
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
16px
;
flex-shrink
:
0
;
}
//
对话框内的颜色显示
.color-value
{
margin-left
:
12px
;
color
:
#606266
;
font-family
:
monospace
;
}
.btn-icon
{
margin-right
:
4px
;
}
</
style
>
src/views/userPage/components/selfActivity.vue
0 → 100644
View file @
ea5de822
<
template
>
<div
class=
"flex-1 flex flex-col"
v-loading=
"loading"
>
<div
class=
"flex-1 p-4 pt-1"
>
<div
class=
"relative"
>
<el-tabs
v-model=
"searchParams.type"
@
tab-change=
"toggleTab"
>
<el-tab-pane
v-for=
"tab in activityTypeListOptions"
:key=
"tab.value"
:label=
"tab.label"
:name=
"tab.value"
/>
</el-tabs>
<div
class=
"absolute right-0 top-2.5 z-1000"
>
<el-icon
size=
"15"
class=
"cursor-pointer hover:rotate-180 transition-all duration-300"
@
click=
"refresh"
><IEpRefresh
/></el-icon>
</div>
</div>
<!-- 加一行提示 -->
<div
class=
"flex justify-end"
>
<p
class=
"text-gray-500 text-sm mb-1 flex items-center gap-1"
>
<el-icon><IEpInfoFilled
/></el-icon>
页面仅展示竞拍成功的记录
</p>
</div>
<div
v-if=
"!list.length"
class=
"flex flex-col items-center justify-center h-64"
>
<div
class=
"w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4"
>
<el-icon
class=
"text-2xl text-gray-300"
><IEpDocument
/></el-icon>
</div>
<div
class=
"text-gray-500 text-lg mb-2"
>
暂无内容
</div>
</div>
<div
v-else
class=
"space-y-4"
>
<el-table
height=
"500"
:data=
"list"
stripe
border
>
<el-table-column
prop=
"name"
label=
"名称"
/>
<el-table-column
prop=
"startingPrice"
label=
"起拍价"
/>
<el-table-column
prop=
"bidPrice"
label=
"支出YA币"
/>
</el-table>
</div>
</div>
<div
v-if=
"list.length"
class=
"flex items-center justify-end px-6 py-4 border-t border-gray-200"
>
<div
class=
"pagination-wrapper bg-white rounded-lg shadow-sm border border-gray-100 p-2"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
@
size-change=
"changePageSize"
@
current-change=
"goToPage"
:page-sizes=
"[10, 20, 30, 40]"
layout=
"prev, pager, next, jumper, total"
:total=
"total"
class=
"custom-pagination"
/>
</div>
</div>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
getSelfAuctionRecord
}
from
'@/api'
import
{
usePageSearch
}
from
'@/hooks'
import
{
activityTypeListOptions
}
from
'@/constants/options'
import
{
ActivityTypeEnum
}
from
'@/constants/enums'
import
type
{
TabPaneName
}
from
'element-plus'
const
toggleTab
=
(
key
:
TabPaneName
)
=>
{
searchParams
.
value
.
type
=
key
as
ActivityTypeEnum
refresh
()
}
const
{
list
,
loading
,
searchParams
,
total
,
refresh
,
goToPage
,
changePageSize
}
=
usePageSearch
(
getSelfAuctionRecord
,
{
defaultParams
:
{
type
:
activityTypeListOptions
[
0
]
!
.
value
,
},
immediate
:
false
,
},
)
onActivated
(()
=>
{
searchParams
.
value
.
type
=
activityTypeListOptions
[
0
]
!
.
value
refresh
()
})
defineExpose
({
refresh
:
()
=>
{
searchParams
.
value
.
type
=
activityTypeListOptions
[
0
]
!
.
value
refresh
()
},
})
</
script
>
src/views/userPage/index.vue
View file @
ea5de822
...
@@ -365,7 +365,7 @@ const handleSwitchAccount = async () => {
...
@@ -365,7 +365,7 @@ const handleSwitchAccount = async () => {
cutEmail
:
selectedEmail
.
value
,
cutEmail
:
selectedEmail
.
value
,
})
})
console
.
log
(
data
)
console
.
log
(
data
)
session
Storage
.
clear
()
local
Storage
.
clear
()
await
userStore
.
getUserInfoByCode
({
await
userStore
.
getUserInfoByCode
({
code
:
data
,
code
:
data
,
isCodeLogin
:
1
,
isCodeLogin
:
1
,
...
@@ -386,7 +386,6 @@ const handleSwitchAccount = async () => {
...
@@ -386,7 +386,6 @@ const handleSwitchAccount = async () => {
}
}
const
handleBackUser
=
()
=>
{
const
handleBackUser
=
()
=>
{
sessionStorage
.
clear
()
wxLogin
(
route
.
fullPath
)
wxLogin
(
route
.
fullPath
)
}
}
...
@@ -402,7 +401,7 @@ const handleClearCache = async () => {
...
@@ -402,7 +401,7 @@ const handleClearCache = async () => {
userId
:
userInfo
.
value
.
userId
,
userId
:
userInfo
.
value
.
userId
,
})
})
// 清理sessionStorage
// 清理sessionStorage
session
Storage
.
clear
()
local
Storage
.
clear
()
await
userStore
.
getUserInfoByCode
({
await
userStore
.
getUserInfoByCode
({
code
:
data
,
code
:
data
,
isCodeLogin
:
1
,
isCodeLogin
:
1
,
...
...
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