447 lines
12 KiB
Vue
447 lines
12 KiB
Vue
<script setup lang="ts">
|
|
import {
|
|
CircleAlert,
|
|
Download,
|
|
EllipsisVertical,
|
|
Play
|
|
} from 'lucide-vue-next';
|
|
import { NConfigProvider, NMessageProvider } from "naive-ui";
|
|
import { nextTick, ref } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
const message = useMessage()
|
|
|
|
const props = defineProps({
|
|
item: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
currentType: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
currentState: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
})
|
|
|
|
// 定义 emit
|
|
const emit = defineEmits(['topedRefresh'])
|
|
|
|
const router = useRouter()
|
|
const isDelete = ref(false)
|
|
// 跳转详情
|
|
function toDetails() {
|
|
if (props.currentType === '0') {
|
|
if(props.currentState === 'mallProduct'){
|
|
router.push(`/model-details/${props.item.id}`)
|
|
}else{
|
|
router.push(`/model-details/${props.item.modelId}`)
|
|
}
|
|
}
|
|
else if (props.currentType === '1') {
|
|
if(props.currentState === 'mallProduct'){
|
|
router.push(`/workflow-details/${props.item.id}`)
|
|
}else{
|
|
router.push(`/workflow-details/${props.item.workFlowId}`)
|
|
}
|
|
}else if(props.currentType === '2'){
|
|
onEditPicture()
|
|
}
|
|
}
|
|
|
|
// 获取图片详情进行编辑
|
|
const publishPictureData = ref<any>({})
|
|
async function getPublishPicture() {
|
|
try {
|
|
const res = await request.get(`/image/detail?id=${props.item.id}`)
|
|
if (res.code === 200) {
|
|
publishPictureData.value = res.data
|
|
publishPictureData.value.imagePaths = res.data.imagePaths.split(',')
|
|
// publishPictureData.value.tags = res.data.tags.split(',')
|
|
}
|
|
}
|
|
catch (e) {
|
|
console.log(e)
|
|
}
|
|
}
|
|
|
|
// 处理下拉菜单选项 编辑/删除/置顶
|
|
function handleSelect(event: Event, key: string) {
|
|
event.stopPropagation() // 阻止事件冒泡
|
|
if (key === 'top') {
|
|
handleTop()
|
|
}
|
|
else if (key === 'delete') {
|
|
handleDelete()
|
|
}
|
|
else if (key === 'edit') {
|
|
if (props.currentType === '2') { // 图片
|
|
getPublishPicture()
|
|
showPublishImg()
|
|
}
|
|
else if (props.currentType === '1') { // 工作流
|
|
router.push({
|
|
path: `/publish-workflow`,
|
|
query: {
|
|
type: 'edit',
|
|
id: props.item.id,
|
|
},
|
|
})
|
|
}
|
|
else if (props.currentType === '0') { // 模型
|
|
router.push({
|
|
path: `/publish-model`,
|
|
query: {
|
|
type: 'edit',
|
|
id: props.item.id,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 置顶
|
|
const menuRef = ref(null)
|
|
interface TopUrlType {
|
|
[key: string | number]: string
|
|
}
|
|
const topUrl = ref<TopUrlType>({
|
|
0: 'model',
|
|
1: 'WorkFlow',
|
|
2: 'image',
|
|
})
|
|
async function handleTop() {
|
|
try {
|
|
const res = await request.get(
|
|
`/${topUrl.value[props.currentType]}/${props.item.id}/top?isTop=${!props.item
|
|
.isTop}`,
|
|
)
|
|
if (res.code === 200) {
|
|
message.success('置顶成功!')
|
|
menuRef.value.style.display = 'none';
|
|
// 刷新列表
|
|
emit('topedRefresh')
|
|
}
|
|
}
|
|
catch (e) {}
|
|
}
|
|
|
|
// 删除
|
|
|
|
interface Response {
|
|
code: number
|
|
}
|
|
|
|
// 删除
|
|
async function handleDelete(): Promise<void> {
|
|
isDelete.value = true
|
|
}
|
|
async function onDelete(){
|
|
const { currentType, item } = props
|
|
let url: string
|
|
|
|
switch (currentType) {
|
|
case '0':
|
|
url = `/model/delete?id=${item.id}`
|
|
break
|
|
case '1':
|
|
url = `/WorkFlow/deleteWorkFlow?id=${item.id}`
|
|
break
|
|
default:
|
|
url = `/image/delete?id=${item.id}`
|
|
break
|
|
}
|
|
|
|
try {
|
|
const res: Response = await request.get(url)
|
|
if (res.code === 200) {
|
|
// 刷新列表
|
|
message.success('删除成功!')
|
|
emit('topedRefresh')
|
|
}
|
|
}
|
|
catch (e) {
|
|
// 统一处理错误
|
|
console.error('删除操作失败:', e)
|
|
}
|
|
}
|
|
function getFirstImagePath(imagePaths: string): string {
|
|
if (!imagePaths)
|
|
return ''
|
|
return imagePaths.split(',')[0] || ''
|
|
}
|
|
// 关闭图片
|
|
const isShowPublishPicture = ref<boolean>(false)
|
|
const PublishPictureRef = ref<Payment | null>(null)
|
|
|
|
function showPublishImg() {
|
|
isShowPublishPicture.value = true
|
|
if (PublishPictureRef.value) {
|
|
PublishPictureRef.value.isVisible = true
|
|
}
|
|
}
|
|
|
|
function closePublishImg() {
|
|
isShowPublishPicture.value = false
|
|
if (PublishPictureRef.value) {
|
|
PublishPictureRef.value.isVisible = false
|
|
}
|
|
}
|
|
|
|
// 显示图片的编辑
|
|
const isShowEditorPicture = ref(false)
|
|
interface EditUserInfoType {
|
|
isVisible: boolean
|
|
}
|
|
const editUserInfoRef = ref<EditUserInfoType | null>(null)
|
|
function onEditPicture() {
|
|
isShowEditorPicture.value = true
|
|
nextTick(()=>{
|
|
if(editUserInfoRef.value){
|
|
editUserInfoRef.value.isVisible = true
|
|
}
|
|
})
|
|
}
|
|
function closeEditorPicture(){
|
|
isShowEditorPicture.value = false
|
|
}
|
|
|
|
function updateLike(type:number){
|
|
if (props.item.isLike === 1) {
|
|
props.item.isLike = 0;
|
|
props.item.likeNum -= 1;
|
|
} else {
|
|
props.item.isLike = 1;
|
|
props.item.likeNum += 1;
|
|
}
|
|
}
|
|
function showMenu(){
|
|
menuRef.value.style.display = 'block';
|
|
}
|
|
function hiddenMenu(){
|
|
menuRef.value.style.display = 'none';
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div v-if="currentState === 'like' && currentType === '2'">
|
|
<div
|
|
class="h-80 rounded-2xl border border-solid border-[#e5e7eb] overflow-hidden cursor-pointer relative group"
|
|
@click="toDetails"
|
|
>
|
|
<img
|
|
class="w-full h-full object-cover block"
|
|
:src="getFirstImagePath(item.imagePaths)"
|
|
alt=""
|
|
>
|
|
<div
|
|
class="absolute w-full h-full top-0 left-0 flex justify-between px-4 py-4 box-border bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
|
|
>
|
|
<div class="flex items-center h-6">
|
|
<img
|
|
class="w-6 h-6 rounded-full"
|
|
:src="item.userAvatar"
|
|
alt="头像"
|
|
>
|
|
<span class="ml-2 h-5 text-gray-300 text-[12px]">{{ item.userName }}</span>
|
|
</div>
|
|
<div class="flex items-center h-7 justify-center rounded-xl bg-[#fceceb] p-2">
|
|
<img
|
|
src="@/assets/img/heart.png"
|
|
class="w-3 h-3 mr-1"
|
|
alt="❤️"
|
|
>
|
|
<span class="text-xs text-[#000]">{{ item.likeNum }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
<div
|
|
class="h-80 rounded-2xl overflow-hidden cursor-pointer relative border border-solid border-[#e5e7eb]"
|
|
@click="toDetails"
|
|
>
|
|
<img v-if="currentType === '0'" class="w-full h-full object-cover block" :src="item.surfaceUrl" alt="">
|
|
<img v-if="currentType === '1'" class="w-full h-full object-cover block" :src="item.coverPath" alt="">
|
|
<img v-if="currentType === '2'" class="w-full h-full object-cover block" :src="getFirstImagePath(item.imagePaths)" alt="">
|
|
<div
|
|
v-if="currentState === 'mallProduct' && item.isTop === 1"
|
|
class="text-[#58c08e] border-[#58c08e] border-solid border-[1px] bg-white rounded-lg px-1 w-10 text-[12px] ml-2 text-center absolute top-4 right-8"
|
|
>
|
|
置顶
|
|
</div>
|
|
<!-- 在发布中 auditStatus等于代表没有审批通过 -->
|
|
<div
|
|
v-if="currentState === 'mallProduct' && item.auditStatus === 4 || item.auditStatus === 3"
|
|
class="absolute top-0 left-0 w-full h-full text-gray-400 bg-black/50 flex justify-center items-center flex-col"
|
|
>
|
|
<component
|
|
:is="CircleAlert"
|
|
class="h-[40px] w-[40px] text-white menu-icon m-1 text-gray-400"
|
|
/>
|
|
{{ item.auditStatus === 3 ? '审核中' : '未通过' }}
|
|
</div>
|
|
<div
|
|
class="modelSelectByUserIdModel w-full h-full top-0 left-0 flex px-4 py-4 box-border"
|
|
>
|
|
<div
|
|
v-if="currentState === 'mallProduct' && currentType === '0'"
|
|
class="text-white text-[12px] px-3 bg-[#000] bg-opacity-40 rounded-lg h-[20px] leading-relaxed"
|
|
>
|
|
<span>
|
|
{{ item.modelType }}
|
|
</span>
|
|
</div>
|
|
<div
|
|
v-if="currentState === 'mallProduct' && currentType === '1'"
|
|
class="text-white text-[12px] px-3 bg-[#000] bg-opacity-40 rounded-lg h-[20px] leading-relaxed"
|
|
>
|
|
工作流
|
|
</div>
|
|
<div
|
|
v-if="currentState === 'mallProduct'"
|
|
class="modelSelectByUserIdModel-mask h-1/3 absolute top-0 left-0 bg-gradient-to-b from-black/100 to-transparent px-4 py-4 text-white box-border flex justify-end"
|
|
>
|
|
<div class="menu-content">
|
|
<component
|
|
@mouseenter="showMenu"
|
|
:is="EllipsisVertical"
|
|
class="h-[18px] w-[18px] text-white menu-icon-ellipsis"
|
|
/>
|
|
<div
|
|
@mouseleave="hiddenMenu"
|
|
ref="menuRef"
|
|
class="menu-group text-[#000000] text-[12px] bg-white rounded-lg text-center w-20 mt-2 hidden"
|
|
>
|
|
<div class="menu-item" @click="(event) => handleSelect(event, 'edit')">
|
|
编辑
|
|
</div>
|
|
<div
|
|
class="menu-item text-red-600"
|
|
@click="(event) => handleSelect(event, 'delete')"
|
|
>
|
|
删除
|
|
</div>
|
|
<div class="menu-item" @click="(event) => handleSelect(event, 'top')">
|
|
{{ item.isTop === 1 ? "取消置顶" : "置顶" }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="currentType !== '2'"
|
|
class="absolute bottom-0 left-0 px-4 py-2 text-white box-border flex justify-between items-center"
|
|
>
|
|
<component :is="Play" class="h-[14px] w-[14px] text-white menu-icon m-1" />
|
|
<span v-if="currentType === '0'">
|
|
{{ item.reals || 0 }}
|
|
</span>
|
|
<span v-if="currentType === '1'">
|
|
{{ item.useNumber || 0 }}
|
|
</span>
|
|
<component
|
|
:is="Download"
|
|
class="h-[14px] w-[14px] text-white menu-icon m-1"
|
|
/>
|
|
<span v-if="currentType === '0'">
|
|
{{ item.numbers || 0 }}
|
|
</span>
|
|
<span v-if="currentType === '1'">
|
|
{{ item.downloadNumber || 0 }}
|
|
</span>
|
|
<!-- <component
|
|
:is="ImagePlay"
|
|
class="h-[14px] w-[14px] text-white menu-icon m-1"
|
|
/>0 -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="currentType !== '2'" class="mt-2 text-[12px] text-[#67787e]">
|
|
<div class="text-[#19191c] text-[14px] max-w-xs truncate ">
|
|
<span v-if="currentType === '0'">
|
|
{{ item.modelName }}
|
|
</span>
|
|
<span v-if="currentType === '1'">
|
|
{{ item.workflowName }}
|
|
</span>
|
|
|
|
<!-- <span>{{ item.userName }}</span> -->
|
|
</div>
|
|
<div class="flex mt-1">
|
|
<img
|
|
class="block w-4 h-4 rounded-full mr-2"
|
|
:src="item.userAvatar"
|
|
alt=""
|
|
>
|
|
<span class="text-xs text-gray-500">{{ item.userName }} </span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<NConfigProvider>
|
|
<NMessageProvider>
|
|
<div v-if="isShowEditorPicture">
|
|
<PictureDetail @close-editor-picture="closeEditorPicture" ref="editUserInfoRef" :item="item" @update-like="updateLike"/>
|
|
</div>
|
|
<Publish-picture v-if="isShowPublishPicture" type="edit" ref="PublishPictureRef" :form-data="publishPictureData" @close-publish-img="closePublishImg" />
|
|
</NMessageProvider>
|
|
</NConfigProvider>
|
|
<n-modal
|
|
v-model:show="isDelete"
|
|
:mask-closable="false"
|
|
preset="dialog"
|
|
title="提示!"
|
|
content="确定要将模型删除? 模型删除后无法找回"
|
|
negative-text="取消"
|
|
positive-text="确认"
|
|
@negative-click="isDelete = false"
|
|
@positive-click="onDelete"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
.menu-icon-ellipsis:hover + .menu-group{
|
|
display: block;
|
|
}
|
|
.modelSelectByUserIdModel {
|
|
position: absolute;
|
|
&:hover {
|
|
.modelSelectByUserIdModel-mask {
|
|
display: block;
|
|
}
|
|
}
|
|
.modelSelectByUserIdModel-mask {
|
|
position: absolute;
|
|
width: 100%;
|
|
display: none;
|
|
.menu-content {
|
|
width: 20px;
|
|
height: 30px;
|
|
position: absolute;
|
|
right: 10px;
|
|
}
|
|
.menu-content:hover {
|
|
.menu-group {
|
|
display: block;
|
|
}
|
|
}
|
|
.menu-group {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 0;
|
|
.menu-item {
|
|
padding: 4px 0 4px 0;
|
|
margin: 4px;
|
|
border-radius: 2px;
|
|
&:hover {
|
|
background-color: #eeeded;
|
|
// border: solid;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|