PixelAI-admin/src/views/service/recommend/index.vue

536 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="system-dept-container layout-padding">
<el-card shadow="hover" class="layout-padding-auto">
<div class="system-dept-search mb15">
<!-- 发布者<el-input size="default" placeholder="请输入发布用户名称" v-model="state.tableData.param.userName"
class="ml10 mr10" style="max-width: 180px" clearable></el-input> -->
作品类型:<el-select size="default" v-model="state.tableData.param.serviceName" placeholder="请选择作品类型"
clearable class="ml10 mr10" style="max-width: 180px" filterable>
<el-option v-for="(item,index) in state.special.data" :key="index" :label="item.name" :value="item.name"></el-option>
</el-select>
<el-button @click="getTableData" size="default" type="primary" class="ml10">
<el-icon>
<ele-Search />
</el-icon>
查询
</el-button>
<el-button @click="reset" size="default" type="primary" class="ml10">
<el-icon>
<ele-RefreshRight />
</el-icon>
重置
</el-button>
<el-button @click="state.recommend.show = true" size="default" type="success" class="ml10">
<el-icon>
<ele-FolderAdd />
</el-icon>
添加推荐作品
</el-button>
</div>
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
<el-table-column align="center" type="index" label="序号" width="100"/>
<el-table-column align="center" prop="sourcePath" label="原图">
<template #default="scope">
<el-image v-if="scope.row.sourcePath" :src="getImagePath(scope.row.sourcePath)" lazy
preview-teleported="true" :preview-src-list="[getImagePath(scope.row.sourcePath)]"/>
<div v-else>暂无</div>
</template>
</el-table-column>
<el-table-column align="center" prop="path" label="作品">
<template #default="scope">
<el-image :src="getImagePath(scope.row.path)" lazy
preview-teleported="true" :preview-src-list="[getImagePath(scope.row.path)]"/>
</template>
</el-table-column>
<el-table-column prop="serviceName" align="center" label="作品类型" show-overflow-tooltip></el-table-column>
<el-table-column prop="number" align="center" label="排序" show-overflow-tooltip></el-table-column>
<el-table-column prop="createtime" align="center" label="时间" :formatter="dateFormatter" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="200" align="center">
<template #default="scope">
<!-- <el-button size="small" text type="primary" @click="toShowDetail(scope.row.id)">查看详情</el-button> -->
<el-button size="small" text type="primary" @click="reviewRecommend(scope.row)">修改</el-button>
<el-button size="small" text type="danger" @click="deleteRecommend(scope.row.id)">删除</el-button>
<!-- <el-button size="small" v-else text type="primary" @click="audit(scope.row)">重新审核</el-button> -->
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="onHandleSizeChange"
@current-change="onHandleCurrentChange"
class="mt15"
:pager-count="5"
:page-sizes="[10, 20, 30]"
v-model:current-page="state.tableData.param.current"
background
v-model:page-size="state.tableData.param.size"
layout="total, sizes, prev, pager, next, jumper"
:total="state.tableData.total"
>
</el-pagination>
</el-card>
<!-- 回复弹窗 -->
<el-dialog style="height: 200px;" :title="state.auditDialog.title" v-model="state.auditDialog.show" width="400px">
<div class="dialog-content">
<el-form ref="replayFormRef" v-loading="state.auditDialog.loading" label-width="80px" :model="state.auditDialog.form">
<el-radio-group class="dialog-radio" v-model="state.auditDialog.form.status">
<el-radio :value="2">通过</el-radio>
<el-radio :value="3">不通过</el-radio>
</el-radio-group>
<div class="dialog-footer">
<el-button @click="state.auditDialog.show = false">取消</el-button>
<el-button type="primary">确定</el-button>
</div>
</el-form>
</div>
</el-dialog>
<!-- 添加推荐作品 -->
<el-dialog :title="state.recommend.title" v-model="state.recommend.show" width="400px">
<el-form v-loading="state.recommend.loading" ref="recommendFormRef" :model="state.recommend.form" :rules="state.recommend.rules" size="default" label-width="100px">
<el-row :gutter="35">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="作品类型:" prop="serviceName">
<el-select size="default" v-model="state.recommend.form.serviceName" placeholder="请选择作品类型" clearable filterable>
<el-option v-for="(item,index) in state.special.data" :key="index" :label="item.name" :value="item.name"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="排序号:" prop="number">
<el-input placeholder="请输入排序号" min="0" v-model="state.recommend.form.number" type="number"></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="原图:" class="iconImg">
<!-- 上传文件 -->
<el-upload ref="ordUploadRef" class="h100 personal-user-left-upload" action="#" list-type="picture-card"
:auto-upload="false" :limit="1" :class="{ hide: state.recommend.picture.ordHide }" @change="handleOrdUploadChange" accept='image/*'>
<template #default>
<el-icon><Plus /></el-icon>
</template>
<template #file="{ file }">
<div>
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<el-icon><zoom-in /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleOrdRemove(file)">
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
</template>
</el-upload>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="效果图:" class="iconImg">
<!-- 上传文件 -->
<el-upload ref="effUploadRef" class="h100 personal-user-left-upload" action="#" list-type="picture-card"
:auto-upload="false" :limit="1" :class="{ hide: state.recommend.picture.effHide }" @change="handleEffUploadChange" accept='image/*'>
<template #default>
<el-icon><Plus /></el-icon>
</template>
<template #file="{ file }">
<div>
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<el-icon><zoom-in /></el-icon>
</span>
<span v-if="!disabled" class="el-upload-list__item-delete" @click="handleEffRemove(file)">
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
</template>
</el-upload>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default">取 消</el-button>
<el-button type="primary" @click="onSubmit" size="default">确 定</el-button>
</span>
</template>
</el-dialog>
<!-- 封面预览弹窗 -->
<el-dialog v-model="dialogVisible">
<img width="100%" w-full :src="dialogImageUrl" alt="预览" />
</el-dialog>
</div>
</template>
<script setup lang="ts" name="shares">
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
import { recommendApi } from '/@/api/service/recommend';
import { applyApi } from '/@/api/service/apply';
import { photosApi } from '/@/api/photos';
import { ElMessage, ElMessageBox, TableColumnCtx, UploadFile, UploadFiles } from 'element-plus';
import { Delete, Plus, ZoomIn } from '@element-plus/icons-vue';
// 表格数据
const state = reactive<any>({
tableData: {
data: [],
total: 0,
loading: false,
param: {
current: 1,
size: 10,
serviceName: '',
isBackend: 1,
number: ''
},
},
special: {
data: [],
},
auditDialog: {
loading: false,
form: {
id: '',
status: 2
},
show: false,
title: '作品审核',
},
recommend: {
loading: false,
form: {},
rules: {
// photoSourceId: { required: true, message: '请输入应用名称', trigger: 'blur' },
photoTargetId: { required: false, message: '请上传推荐作品', trigger: 'blur' },
serviceName: { required: true, message: '请选择作品类型', trigger: 'blur' },
number: { required: true, message: '请输入排序号', trigger: 'blur' }
},
show: false,
title: '新增推荐作品',
picture:{
ordFile: {},
ordHide: false,
effFile: {},
effHide: false
}
}
});
// 引入 api 请求接口
const redApi = recommendApi();
const aplApi = applyApi();
const photoApi = photosApi();
// 图标弹窗
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
// 定义变量内容
const recommendFormRef = ref();
const ordUploadRef = ref();
const effUploadRef = ref();
// 图标上传禁用
const disabled = ref(false);
// 获取专题列表
const getSpecialList = async() => {
try {
state.tableData.loading = true;
let res = await aplApi.getAllServices();
if(res?.success){
state.special.data = res.data;
}else{
ElMessage.error('专题列表获取失败!');
}
} catch (error) {
} finally {
state.tableData.loading = false;
}
};
// 图片格式化
const getImagePath = (path: string) => {
if(!path) return;
let index = path?.indexOf('?');
return path?.includes('://') ? path.substring(0,(!index||index===-1) ? path.length : index) : encodeURI(path);
}
// 获取表格数据
const getTableData = async() => {
try {
state.tableData.loading = true;
let res = await redApi.getRecommendList(state.tableData.param);
if(res?.success){
state.tableData.data = res.data.records;
state.tableData.total = res.data.total;
}else{
ElMessage.error('推荐作品列表获取失败!');
}
} catch (error) {
ElMessage.error('推荐作品列表获取失败!');
} finally {
state.tableData.loading = false;
}
};
// 修改排序号
const reviewRecommend = (row:any) => {
ElMessageBox.prompt('排序号','编辑',{
inputValue: `${row.number}`,
inputPattern:/^(0|[1-9][0-9]*)$/,
inputErrorMessage: '请输入大于等于0的数字',
inputPlaceholder: '请输入排序号'
}).then(async({ value }) => {
let res = await redApi.updateRecommend({id: row.id,number: Number(value)});
if(res?.success){
// getTableData();
row.number = Number(value);
ElMessage.success('修改成功!');
}else{
ElMessage.error('修改失败!');
}
})
.catch(() => {})
}
// 删除推荐
const deleteRecommend = (id:Number) =>{
ElMessageBox.confirm('是否确定删除该推荐?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async() => {
try {
state.tableData.loading = true;
let res = await redApi.deleteRecommend(id);
if(res?.success){
await getTableData();
ElMessage.success('推荐作品删除成功!');
} else ElMessage.error('推荐作品删除失败!');
} catch(e) {
ElMessage.error('处理失败!');
} finally {
state.tableData.loading = false;
}
})
}
// 重置
const reset = () =>{
state.tableData.param = {
current: 1,
size: 10,
serviceName: '',
isBackend: 1
}
getTableData();
}
// 关闭弹窗
const closeDialog = () => {
setTimeout(() => {
state.recommend.show = false;
state.recommend.form = {};
handleOrdRemove();
handleEffRemove();
}, 300)
};
// 取消
const onCancel = () => {
closeDialog();
};
// 上传文件
const uploadImageFile = async(file: any,type: any) => {
try {
state.recommend.loading = true;
const formdata = new FormData();
formdata.append('file', file);
let res = await photoApi.uploadPictrue(formdata);
if(res?.success){
type === 'ord' ? state.recommend.form.photoSourceId = res.data.id : state.recommend.form.photoTargetId = res.data.id ;
state.recommend.loading = false;
}else{
ElMessage.error('图片上传失败!');
state.recommend.loading = false;
}
} catch (error) {
state.recommend.loading = false;
ElMessage.error('图片上传失败!');
}
}
// 图标删除——原图
const handleOrdRemove = (file?: UploadFile) => {
state.recommend.picture.ordFile = {};
state.recommend.form.photoSourceId = '';
ordUploadRef.value.clearFiles();
state.recommend.picture.ordHide = false;
}
// 图标删除——效果图
const handleEffRemove = (file?: UploadFile) => {
state.recommend.picture.effFile = {};
state.recommend.form.photoTargetId = '';
effUploadRef.value.clearFiles();
state.recommend.picture.effHide = false;
}
// 图标图片更改——原图
const handleOrdUploadChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
if(uploadFile.raw.type.includes('image')){
const file:any = uploadFile.raw;
state.recommend.picture.ordFile = file;
state.recommend.picture.ordHide = true;
uploadImageFile(file,'ord');
}else{
ElMessage.error('请上传图片文件!');
ordUploadRef.value.clearFiles();
}
}
// 图标图片更改——效果图
const handleEffUploadChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
if(uploadFile.raw.type.includes('image')){
const file:any = uploadFile.raw;
state.recommend.picture.effFile = file;
state.recommend.picture.effHide = true;
uploadImageFile(file,'eff');
}else{
ElMessage.error('请上传图片文件!');
effUploadRef.value.clearFiles();
}
}
// 图标预览
const handlePictureCardPreview = (file: UploadFile) => {
dialogImageUrl.value = file.url!
dialogVisible.value = true
}
const replayFormRef = ref();
// 提交
const onSubmit = () => {
recommendFormRef.value.validate(async(valid: boolean) => {
if (valid && state.recommend.picture.effHide){
try {
state.recommend.loading = true;
let res = await redApi.saveRecommend(state.recommend.form);
if(res?.success){
ElMessage.success('推荐作品新增成功!');
closeDialog(); // 关闭弹窗
state.tableData.param.current = 1;
getTableData();
}else{
ElMessage.error('推荐作品新增失败!');
}
} catch (error) {
ElMessage.error('处理失败!');
} finally {
state.recommend.loading = false;
}
}else{
ElMessage.error(state.recommend.form.number ? '请上传效果图!' :
(state.recommend.form.serviceName ? '请输入排序号!' : '请选择作品类型!'));
}
});
};
// 取消推荐
const toPublic = (row: any) => {
ElMessageBox.confirm('确定要取消该作品推荐吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async() => {
try {
state.tableData.loading = true;
// let res = await shareApi.saveRelease({ creationId: row.creationId });
// if(res?.success){
// await getTableData();
// ElMessage.success('发布成功!');
ElMessage.warning('功能暂未开放!');
// } else ElMessage.error('发布失败!');
} catch(e) {
ElMessage.error('处理失败!');
} finally {
state.tableData.loading = false;
}
})
}
// 日期格式化
const dateFormatter = (row: any, column: TableColumnCtx<String>) => {
if(row.createtime === null) return '暂无';
let date = new Date(row.createtime);
let mount = date.getMonth() + 1;
let day = date.getDate();
let hour = date.getHours();
let minute = date.getMinutes();
let second = date.getSeconds();
return `${date.getFullYear()}-${mount < 10 ? '0' : ''}${mount}-${day < 10 ? '0' : ''}${day} ${hour < 10 ? '0' : ''}${hour}:${minute < 10 ? '0' : ''}${minute}:${second < 10 ? '0' : ''}${second}`;
}
// 分页改变
const onHandleSizeChange = (val: number) => {
state.tableData.param.size = val;
getTableData();
};
// 分页改变
const onHandleCurrentChange = (val: number) => {
state.tableData.param.current = val;
getTableData();
};
onMounted(() => {
getSpecialList();
getTableData();
})
</script>
<style scoped lang="scss">
.system-dept-container {
:deep(.el-card__body) {
display: flex;
flex-direction: column;
flex: 1;
overflow: auto;
.el-table {
flex: 1;
}
}
}
.iconImg :deep(.hide .el-upload--picture-card) {
display: none;
}
.dialog-content{
padding: 0;
display: flex;
flex-direction: column;
}
.dialog-radio{
display: flex;
justify-content: center;
}
.dialog-footer{
margin-top: 20px;
display: flex;
justify-content: center;
}
::v-deep .el-image {
width: 75px; // 固定图片宽度
height: 75px; // 固定图片高度
object-fit: cover; // 图片居中剪裁
// display: block;
}
</style>