Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mengchangaigc
Project
Project
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
姚珂
mengchangaigc
Commits
93b4c33f
Commit
93b4c33f
authored
Aug 20, 2026
by
黄同智
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
布局图片管理的详情,音频管理的详情页和交互
parent
83a3b8c0
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
695 additions
and
11 deletions
+695
-11
index.ts
apps/web-vue/src/router/index.ts
+12
-0
Item.vue
apps/web-vue/src/views/resource/audio/components/Item.vue
+1
-1
detail.vue
apps/web-vue/src/views/resource/audio/detail.vue
+348
-0
index.vue
apps/web-vue/src/views/resource/audio/index.vue
+9
-2
detail.vue
apps/web-vue/src/views/resource/image/detail.vue
+313
-0
index.vue
apps/web-vue/src/views/resource/image/index.vue
+9
-2
detail.vue
apps/web-vue/src/views/resource/material/detail.vue
+3
-6
No files found.
apps/web-vue/src/router/index.ts
View file @
93b4c33f
...
...
@@ -69,11 +69,23 @@ const routes = [
meta
:
{
title
:
'图片管理'
,
icon
:
''
,
affix
:
true
}
},
{
path
:
'image/detail/:id'
,
// 动态参数 :id
name
:
'ImageDetail'
,
component
:
()
=>
import
(
'@/views/resource/image/detail.vue'
),
meta
:
{
title
:
'图片详情'
,
hidden
:
true
}
// hidden: true 表示不在左侧菜单显示
},
{
path
:
'audio'
,
name
:
'Audio'
,
component
:
()
=>
import
(
'@/views/resource/audio/index.vue'
),
meta
:
{
title
:
'音频管理'
,
icon
:
''
,
affix
:
true
}
},
{
path
:
'audio/detail/:id'
,
// 动态参数 :id
name
:
'AudioDetail'
,
component
:
()
=>
import
(
'@/views/resource/audio/detail.vue'
),
meta
:
{
title
:
'音频详情'
,
hidden
:
true
}
// hidden: true 表示不在左侧菜单显示
},
]
},
...
...
apps/web-vue/src/views/resource/audio/components/Item.vue
View file @
93b4c33f
...
...
@@ -11,7 +11,7 @@
<div
class=
"flex-items-center audio-progress-only mt-10"
>
<audio
ref=
"audioRef"
src=
"../../../../../public/houlai.mp3"
@
timeupdate=
"onTimeUpdate"
@
ended=
"onEnded"
@
loadedmetadata=
"onLoadedMetadata"
></audio>
<div
@
click=
"togglePlay"
class=
"minw-44 h-44 round flex-center mr-16 play"
>
{{
isPlaying
?
'⏸️'
:
'▶'
}}
<div
@
click
.
stop
=
"togglePlay"
class=
"minw-44 h-44 round flex-center mr-16 play"
>
{{
isPlaying
?
'⏸️'
:
'▶'
}}
</div>
<el-slider
v-model=
"currentTime"
:max=
"duration"
:step=
"0.1"
:show-tooltip=
"false"
@
change=
"onSliderChange"
@
drag-start=
"isDragging = true"
@
drag-end=
"isDragging = false"
size=
"small"
/>
...
...
apps/web-vue/src/views/resource/audio/detail.vue
0 → 100644
View file @
93b4c33f
<
template
>
<div
class=
"bgmr vh100 p-16 over-y-auto"
>
<section
class=
"bg-fff round-14 p-24 detail-card"
>
<div
class=
"flex justify-between gap-20"
>
<div
class=
"flex-1 minw-0"
>
<div
class=
"flex-items-center"
>
<div
class=
"w-40 h-40 round avatar flex-center mr-12"
>
♙
</div>
<div
class=
"minw-0"
>
<div
class=
"font-bold color-000 ellipsis"
>
月儿弯弯 / 管理组 / 管理部
</div>
<div
class=
"fs-12 color-888 mt-2"
>
发布时间: 2025-04-24 14:43:53
</div>
</div>
</div>
<div
class=
"mt-24 info-grid"
>
<div
class=
"color-666"
>
音频区
</div>
<div
class=
"font-bold color-000 flex-items-center gap-8"
>
<span
v-if=
"!isEditAudioCategory"
>
{{
audioCategoryLabel
}}
</span>
<el-cascader
v-else
v-model=
"editAudioCategory"
:options=
"audioCategoryOptions"
size=
"small"
class=
"w-220"
clearable
/>
<el-button
v-if=
"!isEditAudioCategory"
type=
"primary"
link
@
click=
"startEditAudioCategory"
>
修改
</el-button>
<el-button
v-else
type=
"primary"
link
@
click=
"saveAudioCategory"
>
保存
</el-button>
</div>
<div
class=
"color-666"
>
音频标题
</div>
<div
class=
"font-bold color-000 flex-items-center gap-8"
>
<span
v-if=
"!isEditTitle"
>
{{
audioTitle
}}
</span>
<el-input
v-else
v-model=
"editTitle"
size=
"small"
class=
"w-220"
@
keyup
.
enter=
"saveTitle"
/>
<el-button
v-if=
"!isEditTitle"
type=
"primary"
link
@
click=
"startEditTitle"
>
修改
</el-button>
<el-button
v-else
type=
"primary"
link
@
click=
"saveTitle"
>
保存
</el-button>
</div>
<div
class=
"color-666"
>
公共标签
</div>
<div
class=
"flex-items-center flex-wrap gap-8"
>
<el-tag
v-for=
"tag in publicTags"
:key=
"tag"
class=
"border-none tag-soft"
>
{{
tag
}}
</el-tag>
<el-button
type=
"primary"
link
size=
"small"
@
click=
"addTag('public')"
>
+ 添加公共标签
</el-button>
</div>
<div
class=
"color-666"
>
个人标签
</div>
<div
class=
"flex-items-center flex-wrap gap-8"
>
<el-tag
v-for=
"tag in personalTags"
:key=
"tag"
closable
class=
"border-none tag-main"
@
close=
"removePersonalTag(tag)"
>
{{
tag
}}
</el-tag>
<el-button
type=
"primary"
link
size=
"small"
@
click=
"addTag('personal')"
>
+ 添加个人标签
</el-button>
</div>
<div
class=
"color-666"
>
音频说明
</div>
<div
class=
"color-888"
>
{{
audioDesc
||
'暂无说明'
}}
</div>
</div>
</div>
<div
class=
"flex items-start"
>
<el-button
type=
"primary"
class=
"px-24 round-6 font-bold"
@
click=
"downloadAudio"
>
下载
</el-button>
<el-button
class=
"w-40 h-34 round-6 color-main border-main mr-10"
@
click=
"shareAudio"
>
⌘
</el-button>
<el-dropdown
trigger=
"click"
@
command=
"handleMore"
>
<el-button
class=
"px-18 round-6 color-main border-main"
>
更多操作
</el-button>
<template
#
dropdown
>
<el-dropdown-menu
class=
"more-menu"
>
<el-dropdown-item
command=
"push"
>
推送至团队剪辑
</el-dropdown-item>
<el-dropdown-item
command=
"category"
>
修改所属分类
</el-dropdown-item>
<el-dropdown-item
command=
"message"
>
发送消息提醒
</el-dropdown-item>
<el-dropdown-item
divided
command=
"delete"
class=
"danger-item"
>
放入回收站
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</div>
</div>
</section>
<section
class=
"bg-fff round-14 p-24 mt-16 detail-card"
>
<div
class=
"font-bold color-000 fs-18"
>
{{ audioTitle }}
</div>
<div
class=
"flex-items-center mt-24 audio-player"
>
<audio
ref=
"audioRef"
src=
"/houlai.mp3"
:muted=
"isMuted"
@
timeupdate=
"onTimeUpdate"
@
ended=
"onEnded"
@
loadedmetadata=
"onLoadedMetadata"
></audio>
<div
class=
"w-44 h-44 round flex-center color-main pointer play-btn"
@
click=
"togglePlay"
>
{{ isPlaying ? 'Ⅱ' : '▶' }}
</div>
<span
class=
"ml-16 fs-12 color-000 time-text"
>
{{ formatTime(currentTime) }}
</span>
<el-slider
v-model=
"currentTime"
class=
"mx-16"
:max=
"duration"
:step=
"0.1"
:show-tooltip=
"false"
@
change=
"onSliderChange"
@
drag-start=
"isDragging = true"
@
drag-end=
"isDragging = false"
/>
<span
class=
"fs-12 color-000 time-text"
>
{{ formatTime(duration) }}
</span>
<el-button
class=
"ml-20 border-none color-666"
link
@
click=
"toggleMuted"
>
{{ isMuted ? '静音' : '◔' }}
</el-button>
<el-button
class=
"ml-12 px-16 round-18 font-bold speed-btn"
@
click=
"toggleSpeed"
>
{{ playbackRate }}x倍速
</el-button>
</div>
</section>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
const
audioRef
=
ref
<
HTMLAudioElement
|
null
>
(
null
);
const
currentTime
=
ref
(
0
);
const
duration
=
ref
(
52
);
const
isDragging
=
ref
(
false
);
const
isPlaying
=
ref
(
false
);
const
isMuted
=
ref
(
false
);
const
playbackRate
=
ref
(
1
);
const
audioTitle
=
ref
(
'现在洁牙'
);
const
editTitle
=
ref
(
audioTitle
.
value
);
const
isEditTitle
=
ref
(
false
);
const
audioCategory
=
ref
([
'beauty'
,
'medical'
]);
const
editAudioCategory
=
ref
<
string
[]
>
([]);
const
isEditAudioCategory
=
ref
(
false
);
const
audioDesc
=
ref
(
''
);
const
publicTags
=
ref
([
'场景'
,
'合作达人'
]);
const
personalTags
=
ref
([
'有个人标签'
]);
const
audioCategoryOptions
=
[
{
label
:
'美容美体'
,
value
:
'beauty'
,
children
:
[
{
label
:
'医疗机构'
,
value
:
'medical'
},
{
label
:
'皮肤管理'
,
value
:
'skin'
},
{
label
:
'口腔护理'
,
value
:
'dental'
},
],
},
{
label
:
'生活服务'
,
value
:
'life'
,
children
:
[
{
label
:
'探店口播'
,
value
:
'shop'
},
{
label
:
'本地推广'
,
value
:
'local'
},
],
},
];
const
togglePlay
=
async
()
=>
{
if
(
!
audioRef
.
value
)
return
;
if
(
isPlaying
.
value
)
{
audioRef
.
value
.
pause
();
isPlaying
.
value
=
false
;
return
;
}
try
{
audioRef
.
value
.
playbackRate
=
playbackRate
.
value
;
await
audioRef
.
value
.
play
();
isPlaying
.
value
=
true
;
}
catch
(
err
)
{
isPlaying
.
value
=
false
;
}
};
const
onSliderChange
=
(
val
:
number
)
=>
{
if
(
audioRef
.
value
)
{
audioRef
.
value
.
currentTime
=
val
;
}
};
const
onLoadedMetadata
=
()
=>
{
if
(
audioRef
.
value
)
{
duration
.
value
=
audioRef
.
value
.
duration
;
}
};
const
onTimeUpdate
=
()
=>
{
if
(
!
audioRef
.
value
||
isDragging
.
value
)
return
;
currentTime
.
value
=
audioRef
.
value
.
currentTime
;
};
const
onEnded
=
()
=>
{
isPlaying
.
value
=
false
;
currentTime
.
value
=
0
;
};
const
formatTime
=
(
time
:
number
)
=>
{
if
(
!
time
||
isNaN
(
time
))
return
'00:00'
;
const
minutes
=
Math
.
floor
(
time
/
60
);
const
seconds
=
Math
.
floor
(
time
%
60
);
return
`
${
minutes
.
toString
().
padStart
(
2
,
'0'
)}
:
${
seconds
.
toString
().
padStart
(
2
,
'0'
)}
`
;
};
const
toggleMuted
=
()
=>
{
isMuted
.
value
=
!
isMuted
.
value
;
};
const
toggleSpeed
=
()
=>
{
playbackRate
.
value
=
playbackRate
.
value
===
1
?
1.5
:
playbackRate
.
value
===
1.5
?
2
:
1
;
if
(
audioRef
.
value
)
{
audioRef
.
value
.
playbackRate
=
playbackRate
.
value
;
}
};
const
startEditTitle
=
()
=>
{
editTitle
.
value
=
audioTitle
.
value
;
isEditTitle
.
value
=
true
;
};
const
saveTitle
=
()
=>
{
audioTitle
.
value
=
editTitle
.
value
;
isEditTitle
.
value
=
false
;
ElMessage
.
success
(
'标题已修改'
);
};
const
findCategoryLabel
=
(
value
:
string
[],
options
:
typeof
audioCategoryOptions
)
=>
{
const
first
=
options
.
find
((
item
)
=>
item
.
value
===
value
[
0
]);
const
second
=
first
?.
children
.
find
((
item
)
=>
item
.
value
===
value
[
1
]);
return
first
&&
second
?
`
${
first
.
label
}
/
${
second
.
label
}
`
:
''
;
};
const
audioCategoryLabel
=
computed
(()
=>
findCategoryLabel
(
audioCategory
.
value
,
audioCategoryOptions
));
const
startEditAudioCategory
=
()
=>
{
editAudioCategory
.
value
=
[...
audioCategory
.
value
];
isEditAudioCategory
.
value
=
true
;
};
const
saveAudioCategory
=
()
=>
{
if
(
editAudioCategory
.
value
.
length
<
2
)
{
ElMessage
.
warning
(
'请选择二级分类'
);
return
;
}
audioCategory
.
value
=
[...
editAudioCategory
.
value
];
isEditAudioCategory
.
value
=
false
;
ElMessage
.
success
(
'音频区已修改'
);
};
const
removePersonalTag
=
(
tag
:
string
)
=>
{
personalTags
.
value
=
personalTags
.
value
.
filter
((
item
)
=>
item
!==
tag
);
};
const
addTag
=
(
type
:
'public'
|
'personal'
)
=>
{
const
tag
=
type
===
'public'
?
'新公共标签'
:
'个人收藏'
;
const
list
=
type
===
'public'
?
publicTags
.
value
:
personalTags
.
value
;
if
(
!
list
.
includes
(
tag
))
{
list
.
push
(
tag
);
}
};
const
downloadAudio
=
()
=>
ElMessage
.
success
(
'开始下载音频'
);
const
shareAudio
=
()
=>
ElMessage
.
success
(
'分享链接已生成'
);
const
handleEdit
=
(
name
:
string
)
=>
ElMessage
.
success
(
`
${
name
}
编辑功能已触发`
);
const
handleMore
=
(
command
:
string
)
=>
ElMessage
.
success
(
`已选择:
${
command
}
`
);
</
script
>
<
style
scoped
lang=
"scss"
>
.detail-card
{
max-width
:
976px
;
margin-left
:
auto
;
margin-right
:
auto
;
border
:
1px
solid
#e6ebf3
;
}
.avatar
{
background-color
:
#edf2f8
;
color
:
#7890ad
;
}
.info-grid
{
display
:
grid
;
grid-template-columns
:
74px
1fr
;
row-gap
:
20px
;
}
.tag-soft
{
background-color
:
#f2f6ff
;
color
:
#21324f
;
}
.tag-main
{
background-color
:
rgba
(
var
(
--
main-color
)
,
.08
);
color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
.border-main
{
border
:
1px
solid
rgba
(
var
(
--
main-color
)
,
.35
);
}
.play-btn
{
border
:
2px
solid
rgba
(
var
(
--
main-color
)
,
1
);
flex-shrink
:
0
;
}
.audio-player
{
:deep
(
.el-slider
)
{
flex
:
1
;
}
:deep
(
.el-slider__button
)
{
width
:
14px
;
height
:
14px
;
border
:
none
;
background-color
:
rgb
(
var
(
--
main-color
));
}
:deep
(
.el-slider__bar
)
{
background-color
:
rgb
(
var
(
--
main-color
));
}
:deep
(
.el-slider__runway
)
{
height
:
5px
;
background-color
:
#e6ebf2
;
}
}
.time-text
{
font-family
:
Consolas
,
monospace
;
}
.speed-btn
{
border
:
1px
solid
#e5eaf2
;
background-color
:
#fff
;
}
:deep
(
.more-menu
)
{
min-width
:
158px
;
}
:deep
(
.danger-item
)
{
color
:
#f03b55
;
}
</
style
>
apps/web-vue/src/views/resource/audio/index.vue
View file @
93b4c33f
...
...
@@ -19,8 +19,8 @@
</div>
<div
class=
"flex flex-wrap gap-20"
>
<el-checkbox-group
v-model=
"checkedList"
class=
"flex flex-wrap gap-20 w-full"
>
<div
v-for=
"(item, index) in list"
:key=
"index"
class=
"bg-fff round-12 relative hidden flex-item"
<div
v-for=
"(item, index) in list"
:key=
"index"
@
click=
"goDetail(item)"
class=
"bg-fff round-12 relative hidden
pointer
flex-item"
:class=
"
{ 'is-selected': checkedList.includes(item.id) }">
<Item
:item=
"item"
:isCheck=
"isCheck"
/>
</div>
...
...
@@ -32,9 +32,11 @@
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
'vue'
;
import
{
useRouter
}
from
'vue-router'
import
Classify
from
'../components/Classify.vue'
;
import
Item
from
'@/views/resource/audio/components/Item.vue'
const
router
=
useRouter
()
const
checkedList
=
ref
<
any
>
([])
const
btnIndex
=
ref
(
0
)
const
isCheck
=
ref
(
false
)
...
...
@@ -44,6 +46,11 @@ const switchCheck = () => {
isCheck
.
value
=
!
isCheck
.
value
checkedList
.
value
=
[]
}
const
goDetail
=
(
item
:
any
)
=>
{
if
(
isCheck
.
value
)
return
router
.
push
(
`/resource/audio/detail/
${
item
.
id
}
`
)
}
</
script
>
<
style
scoped
lang=
"scss"
>
...
...
apps/web-vue/src/views/resource/image/detail.vue
0 → 100644
View file @
93b4c33f
<
template
>
<div
class=
"bgmr vh100 p-20 over-y-auto"
>
<el-card
class=
"w-full round-12"
shadow=
"hover"
>
<div
class=
"flex gap-30"
>
<section
style=
"width: 50%;"
>
<div
class=
"bg-fff round-14 hidden preview-box"
>
<el-image
:src=
"currentImage.url"
:zoom-rate=
"1.2"
:max-scale=
"7"
class=
"w-full h-full"
hide-on-click-modal
:min-scale=
"0.2"
:preview-src-list=
"[currentImage.url]"
show-progress
:initial-index=
"4"
fit=
"cover"
/>
</div>
<div
class=
"flex gap-12 mt-18 over-x-auto pb-4"
>
<div
v-for=
"(item, index) in imageList"
:key=
"item.id"
class=
"w-96 h-80 round-10 hidden pointer relative thumb-item"
:class=
"
{ active: activeImageIndex === index }" @click="activeImageIndex = index">
<img
:src=
"item.url"
class=
"w-full h-full cover"
:alt=
"item.name"
/>
<div
class=
"absolute left-0 right-0 bottom-0 px-6 py-4 color-fff fs-10 ellipsis thumb-name"
>
{{
item
.
name
}}
</div>
</div>
</div>
</section>
<section
class=
"flex-1 detail-info"
>
<div
class=
"flex-items-center pb-16 detail-header"
>
<div
class=
"w-34 h-34 round bg-000 color-fff flex-center font-bold mr-12"
>
Z
</div>
<div
class=
"flex-1 minw-0"
>
<div
class=
"font-bold color-000 fs-16 ellipsis"
>
致上互娱 / 默认分组 / 默认团队
</div>
<div
class=
"fs-12 color-888 mt-2"
>
发布时间:2025-05-26 12:25:11
</div>
</div>
</div>
<div
class=
"pt-16"
>
<div
class=
"flex-items-center gap-8"
>
<span
class=
"py-2 px-8 round-4 bg-green color-fff fs-12 font-bold"
>
图片
</span>
<span
class=
"font-bold color-000"
>
美妆护肤 / 致上旗舰店
</span>
<el-button
type=
"primary"
link
@
click=
"handleEdit('所属分类')"
>
修改
</el-button>
</div>
<div
class=
"flex-items-center mt-14"
>
<span
class=
"minw-66 color-666"
>
图片标题:
</span>
<span
v-if=
"!isEditTitle"
class=
"font-bold color-000 ellipsis flex-1"
>
{{
imageTitle
}}
</span>
<el-input
v-else
v-model=
"editTitle"
size=
"small"
class=
"flex-1"
@
keyup
.
enter=
"saveTitle"
/>
<el-button
v-if=
"!isEditTitle"
type=
"primary"
link
@
click=
"startEditTitle"
>
修改
</el-button>
<el-button
v-else
type=
"primary"
link
@
click=
"saveTitle"
>
保存
</el-button>
</div>
<div
class=
"flex-items-center mt-14"
>
<span
class=
"minw-66 color-666"
>
公共标签:
</span>
<div
class=
"flex flex-wrap gap-8 flex-1"
>
<el-tag
v-for=
"tag in publicTags"
:key=
"tag"
class=
"border-none tag-soft"
>
{{
tag
}}
</el-tag>
<el-button
size=
"small"
type=
"primary"
link
@
click=
"addTag('public')"
>
+
添加公共标签
</el-button>
</div>
</div>
<div
class=
"flex-items-center mt-12"
>
<span
class=
"minw-66 color-666"
>
个人标签:
</span>
<div
class=
"flex flex-wrap gap-8 flex-1"
>
<el-tag
v-for=
"tag in personalTags"
:key=
"tag"
closable
class=
"border-none tag-main"
@
close=
"removePersonalTag(tag)"
>
{{
tag
}}
</el-tag>
<el-button
size=
"small"
type=
"primary"
link
@
click=
"addTag('personal')"
>
+
添加个人标签
</el-button>
</div>
</div>
<div
class=
"flex-items-center mt-16"
>
<el-button
class=
"w-30 h-30 border-main color-main round-10"
@
click=
"copyLink"
>
⇅
</el-button>
<el-button
class=
"w-30 h-30 border-main color-main round-10"
@
click=
"toggleStar"
>
{{
isStarred
?
'★'
:
'☆'
}}
</el-button>
<el-button
class=
"w-30 h-30 border-main color-main round-10"
@
click=
"shareImage"
>
⌘
</el-button>
<el-button
type=
"primary"
class=
"round-6 mr-10"
@
click=
"visibleRecord = true"
>
使用记录
</el-button>
<el-dropdown
trigger=
"click"
@
command=
"handleMore"
>
<el-button
class=
"round-6 color-main border-main"
>
更多
</el-button>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
command=
"rename"
>
下载图片
</el-dropdown-item>
<el-dropdown-item
command=
"move"
>
重新智能分类
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</div>
<div
class=
"flex gap-12 mt-20"
>
<el-button
type=
"primary"
class=
"flex-1 h-36 round-10 font-bold"
color=
"#0f128d"
@
click=
"downloadImage"
>
下载无水印图片
</el-button>
<el-button
type=
"primary"
class=
"flex-1 h-36 round-10 font-bold"
color=
"#0f128d"
@
click=
"copyToClip"
>
复制到剪映
</el-button>
</div>
<div
class=
"mt-16 p-16 round-14 info-card fs-12"
>
<div
class=
"lh-26"
>
<div>
下载次数:
<span
class=
"color-000"
>
{{ detail.downloadCount }}
</span></div>
<div>
浏览量:
<span
class=
"color-000"
>
{{ detail.viewCount }}
</span></div>
<div
class=
"color-green"
>
✓ 仅供内部员工学习,不可用于商业用途
</div>
<div
class=
"color-green"
>
✓ 所有人可见
</div>
</div>
<div
class=
"py-12 mt-8 info-line"
>
<div
class=
"flex justify-between"
>
<span
class=
"color-888"
>
可查看时间:
</span>
<div
class=
"text-right lh-20"
>
<div>
小组成员 / 不限
</div>
<div>
团队成员 / 不限
</div>
<div>
其他团队 / 2025-06-25 12:25:11
</div>
</div>
</div>
</div>
<div
class=
"py-12 info-line"
>
<div
class=
"flex justify-between"
>
<span
class=
"color-888"
>
可下载时间:
</span>
<div
class=
"text-right lh-20"
>
<div>
小组成员 / 不限
</div>
<div>
团队成员 / 不限
</div>
<div>
其他团队 / 2025-06-02 12:25:11
</div>
</div>
</div>
</div>
<div
class=
"pt-12 info-line"
>
<div
class=
"flex-between mb-6"
>
<span
class=
"color-888"
>
备注:
</span>
<el-button
v-if=
"!isRemark"
type=
"primary"
link
@
click=
"handleEditRemark"
>
修改
</el-button>
</div>
<div
v-if=
"!isRemark"
class=
"bg-fff round-6 px-12 py-8 color-000"
>
{{ remark }}
</div>
<div
v-else
>
<el-input
type=
"textarea"
v-model=
"remark"
/>
<div
class=
"flex justify-end mt-10"
>
<el-button
link
size=
"small"
@
click=
"isRemark = false"
>
取消
</el-button>
<el-button
type=
"primary"
size=
"small"
@
click=
"isRemark = false"
>
保存
</el-button>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</el-card>
<Dialog
v-model=
"visibleRecord"
bg-color=
"#fff"
width=
"720"
>
<div
class=
"px-20 py-14 font-bold color-000 record-title"
>
使用记录
</div>
<div
class=
"p-20"
>
<SeTable
size=
"small"
:dataList=
"recordList"
:total=
"recordList.length"
>
<el-table-column
prop=
"name"
label=
"使用任务"
/>
<el-table-column
prop=
"user"
label=
"操作人"
width=
"120"
/>
<el-table-column
prop=
"time"
label=
"使用时间"
width=
"180"
/>
<el-table-column
prop=
"status"
label=
"状态"
width=
"120"
>
<
template
#
default=
"{ row }"
>
<el-tag
type=
"success"
>
{{
row
.
status
}}
</el-tag>
</
template
>
</el-table-column>
</SeTable>
</div>
</Dialog>
</div>
</template>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
}
from
'vue'
;
import
{
ElMessage
}
from
'element-plus'
;
import
imageA
from
'@/static/image/huaban.png'
;
import
imageB
from
'@/static/image/meinv.png'
;
const
activeImageIndex
=
ref
(
0
);
const
imageList
=
ref
([
{
id
:
1
,
name
:
'微信图片_20230323...'
,
url
:
imageA
},
{
id
:
2
,
name
:
'微信图片_2023032...'
,
url
:
imageB
}
]);
const
currentImage
=
computed
(()
=>
imageList
.
value
[
activeImageIndex
.
value
]);
const
imageTitle
=
ref
(
'防晒植物提取精华液展图.jpg'
);
const
editTitle
=
ref
(
imageTitle
.
value
);
const
isEditTitle
=
ref
(
false
);
const
isStarred
=
ref
(
false
);
const
visibleRecord
=
ref
(
false
);
const
publicTags
=
ref
([
'场景:测试2'
,
'白爆款: 主图'
,
'高清无水印'
]);
const
personalTags
=
ref
([
'常用精选'
,
'团队必用'
]);
const
detail
=
{
downloadCount
:
0
,
viewCount
:
0
,
};
const
recordList
=
[
{
name
:
'618 主图换新任务'
,
user
:
'张三'
,
time
:
'2025-06-01 12:20'
,
status
:
'已使用'
},
{
name
:
'防晒素材复用任务'
,
user
:
'李四'
,
time
:
'2025-06-02 09:40'
,
status
:
'已使用'
},
];
const
startEditTitle
=
()
=>
{
editTitle
.
value
=
imageTitle
.
value
;
isEditTitle
.
value
=
true
;
};
const
saveTitle
=
()
=>
{
imageTitle
.
value
=
editTitle
.
value
;
isEditTitle
.
value
=
false
;
ElMessage
.
success
(
'标题已修改'
);
};
const
removePersonalTag
=
(
tag
:
string
)
=>
{
personalTags
.
value
=
personalTags
.
value
.
filter
((
item
)
=>
item
!==
tag
);
};
const
addTag
=
(
type
:
'public'
|
'personal'
)
=>
{
const
tag
=
type
===
'public'
?
'新品主推'
:
'个人收藏'
;
const
list
=
type
===
'public'
?
publicTags
.
value
:
personalTags
.
value
;
if
(
!
list
.
includes
(
tag
))
{
list
.
push
(
tag
);
}
};
const
toggleStar
=
()
=>
{
isStarred
.
value
=
!
isStarred
.
value
;
ElMessage
.
success
(
isStarred
.
value
?
'已收藏'
:
'已取消收藏'
);
};
const
remark
=
ref
(
'已完成电商首图审核与裁剪,高清无瑕疵,建议优先推广。'
)
const
isRemark
=
ref
(
false
)
const
copyLink
=
()
=>
ElMessage
.
success
(
'链接已复制'
);
const
shareImage
=
()
=>
ElMessage
.
success
(
'分享链接已生成'
);
const
downloadImage
=
()
=>
ElMessage
.
success
(
'开始下载无水印图片'
);
const
copyToClip
=
()
=>
ElMessage
.
success
(
'已复制到剪映'
);
const
handleEdit
=
(
name
:
string
)
=>
ElMessage
.
success
(
`
${
name
}
编辑功能已触发`
);
const
handleMore
=
(
command
:
string
)
=>
ElMessage
.
success
(
`已选择:
${
command
}
`
);
// 修改备注
const
handleEditRemark
=
()
=>
{
isRemark
.
value
=
true
}
</
script
>
<
style
scoped
lang=
"scss"
>
.preview-box
{
height
:
calc
(
100vh
-
150px
);
min-height
:
420px
;
max-height
:
620px
;
box-shadow
:
0
0
0
1px
#e9edf5
;
}
.thumb-item
{
flex-shrink
:
0
;
box-shadow
:
0
0
0
1px
#e3e9f3
;
&
.active
{
// box-shadow: 0 0 0 2px rgba(var(--main-color), 1);
border
:
2px
solid
rgba
(
var
(
--
main-color
)
,
1
);
}
}
.thumb-name
{
background
:
linear-gradient
(
to
top
,
rgba
(
0
,
0
,
0
,
.55
)
,
rgba
(
0
,
0
,
0
,
0
));
}
.detail-header
,
.record-title
{
border-bottom
:
1px
solid
#edf0f5
;
}
.bg-green
{
background-color
:
#00b779
;
}
.color-green
{
color
:
#00a86b
;
}
.border-main
{
border
:
1px
solid
rgba
(
var
(
--
main-color
)
,
.45
);
}
.tag-soft
{
background-color
:
#f3f6ff
;
color
:
#2c3c62
;
}
.tag-main
{
background-color
:
rgba
(
var
(
--
main-color
)
,
.1
);
color
:
rgba
(
var
(
--
main-color
)
,
1
);
}
.info-card
{
border
:
1px
solid
#edf0f5
;
background-color
:
#f8fafc
;
}
.info-line
{
border-top
:
1px
solid
#e8edf5
;
}
@media
(
max-width
:
1100px
)
{
.detail-layout
{
flex-direction
:
column
;
}
.detail-info
{
width
:
100%
;
}
}
</
style
>
apps/web-vue/src/views/resource/image/index.vue
View file @
93b4c33f
...
...
@@ -19,8 +19,8 @@
</div>
<div
class=
"flex flex-wrap gap-20"
>
<el-checkbox-group
v-model=
"checkedList"
class=
"flex flex-wrap gap-20 w-full"
>
<div
v-for=
"(item, index) in list"
:key=
"index"
class=
"w-200 bg-fff round-12 relative hidden flex-item"
<div
v-for=
"(item, index) in list"
:key=
"index"
@
click=
"goDetail(item)"
class=
"w-200 bg-fff round-12 relative hidden
pointer
flex-item"
:class=
"
{ 'is-selected': checkedList.includes(item.id) }">
<Item
:item=
"item"
:isCheck=
"isCheck"
/>
</div>
...
...
@@ -33,10 +33,12 @@
<
script
setup
lang=
"ts"
>
import
{
ref
}
from
'vue'
;
import
{
useRouter
}
from
'vue-router'
import
Classify
from
'../components/Classify.vue'
;
import
Item
from
'@/views/resource/image/components/Item.vue'
import
UploadDialog
from
'./components/UploadDialog.vue'
;
const
router
=
useRouter
()
const
checkedList
=
ref
<
any
>
([])
const
btnIndex
=
ref
(
0
)
const
isCheck
=
ref
(
false
)
...
...
@@ -47,6 +49,11 @@ const switchCheck = () => {
checkedList
.
value
=
[]
}
const
goDetail
=
(
item
:
any
)
=>
{
if
(
isCheck
.
value
)
return
router
.
push
(
`/resource/image/detail/
${
item
.
id
}
`
)
}
// 上传视频的弹窗内容
...
...
apps/web-vue/src/views/resource/material/detail.vue
View file @
93b4c33f
...
...
@@ -197,6 +197,9 @@ const ascOptions = [
color
:
rgba
(
var
(
--
main-color
)
,
1
);
// flex: 0 0 calc((100% - 10px * 2) / 3);
}
.bordedr
{
box-shadow
:
0
0
0
1px
rgba
(
var
(
--
main-color
)
,
.1
);
}
.active
{
background-color
:
rgba
(
var
(
--
main-color
)
,
1
);
...
...
@@ -235,12 +238,6 @@ const ascOptions = [
box-shadow
:
0
0
0
1px
#eee
;
}
:deep
(
.myselect
)
{
.el-select__wrapper
{
border-radius
:
12px
;
}
}
/* 1600px 以下:一行 5 个 */
@media
(
max-width
:
1500px
)
{
.flex-item1
{
...
...
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