PixelAI-admin/src/views/article/component/upload.vue

363 lines
12 KiB
Vue
Raw Normal View History

2024-10-31 09:56:55 +08:00
<template>
<div class="layout-pd">
<el-card v-loading="state.loading" shadow="hover" header="文章详情">
<el-form ref="articleFormRef" :model="state.data" :rules="state.rules" size="large" label-width="100px" class="mt20 mb20">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="封面:" class="coverImg">
<!-- 上传文件 -->
2024-10-31 17:11:17 +08:00
<el-upload ref="uploadRef" class="h100 personal-user-left-upload" action="#" list-type="picture-card" :file-list="state.fileArray"
:auto-upload="false" :limit="1" :class="{ hide: state.coverHide }" @change="handleUploadChange" accept='image/*'>
2024-10-31 09:56:55 +08:00
<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>
2024-10-31 17:11:17 +08:00
<!-- <span
2024-10-31 09:56:55 +08:00
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleDownload(file)"
>
<el-icon><Download /></el-icon>
2024-10-31 17:11:17 +08:00
</span> -->
2024-10-31 09:56:55 +08:00
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
</template>
</el-upload>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="模块名称:" prop="moduleName">
2024-10-31 17:11:17 +08:00
<el-select size="default" @change="handleChangeModule" v-model="state.data.moduleName" placeholder="请选择模块" clearable>
2024-10-31 09:56:55 +08:00
<el-option :data-op="item.id" v-for="(item,index) in moduleList" :key="index" :label="item.moduleName" :value="item.moduleName"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="标签名称:" prop="labelName">
2024-10-31 17:11:17 +08:00
<el-select size="default" v-model="state.data.labelName" placeholder="请选择标签" clearable class="ml10">
<el-option v-for="(item,index) in labelList" :key="index" :label="item.name" :value="item.name"></el-option>
</el-select>
2024-10-31 09:56:55 +08:00
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="标题:" prop="title">
<el-input v-model="state.data.title" placeholder="请输入标题" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="文章类型:" prop="articletype">
<el-select size="default" v-model="state.data.articletype" placeholder="请选择文章类型" clearable>
<el-option label="图文" :value="0"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="是否置顶:" prop="top">
<el-switch v-model="state.data.top" />
</el-form-item>
</el-col>
</el-row>
<el-form-item prop="text" label-width="0px">
2024-11-01 23:31:28 +08:00
<Editor v-model:get-html="state.data.text" style="width: 100%;"/>
2024-10-31 09:56:55 +08:00
</el-form-item>
<el-row class="flex mt15">
<div class="flex-margin" style="width: 100%;display: flex;justify-content: flex-end;">
2024-10-31 17:11:17 +08:00
<el-button size="larger" type="info" @click="cancel">
<SvgIcon name="ele-RefreshLeft" />
取消
</el-button>
2024-10-31 09:56:55 +08:00
<el-button size="larger" type="primary" @click="onSubmitForm">
<SvgIcon name="iconfont icon-shuxing" />
保存
</el-button>
</div>
</el-row>
</el-form>
</el-card>
<!-- 封面预览弹窗 -->
<el-dialog v-model="dialogVisible">
2024-11-01 23:31:28 +08:00
<img width="100%" w-full :src="dialogImageUrl" alt="预览" />
2024-10-31 09:56:55 +08:00
</el-dialog>
</div>
</template>
<script setup lang="ts" name="articleDetail">
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
import { articleApi } from '/@/api/article';
2024-10-31 17:11:17 +08:00
import { useRoute, useRouter } from 'vue-router';
2024-10-31 09:56:55 +08:00
import { ElMessage, UploadFile, UploadFiles } from 'element-plus';
2024-10-31 17:11:17 +08:00
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue';
import mittBus from '/@/utils/mitt';
2024-10-31 09:56:55 +08:00
// 引入组件
const Editor = defineAsyncComponent(() => import('/@/components/editor/index.vue'));
2024-10-31 17:11:17 +08:00
// 封面基本路径
const viteUrl = import.meta.env.VITE_API_URL;
2024-10-31 09:56:55 +08:00
// 引入 api 请求接口
const artApi = articleApi();
// 模块列表
const moduleList = ref([]);
2024-10-31 17:11:17 +08:00
// 标签列表
const labelList = ref([]);
2024-10-31 09:56:55 +08:00
// 获取文章id
const route = useRoute();
2024-10-31 17:11:17 +08:00
const router = useRouter();
2024-10-31 09:56:55 +08:00
const moduleName:any = route.query.moduleName;
const labelName:any = route.query.labelName;
2024-11-12 17:35:06 +08:00
const id:any = route.query.id;
2024-10-31 09:56:55 +08:00
const state = reactive({
data: {
labelName: '',
moduleName: '',
title: '',
articletype: '',
photo: '',
text: '',
top: false,// 是否置顶这里提交的时候要换成0或1
},
loading: false,
rules: {
moduleName: { required: true, message: '请选择模块', trigger: 'blur' },
labelName: { required: true, message: '请输入标签名称', trigger: 'blur' },
title: { required: true, message: '请输入标题', trigger: 'blur' },
articletype: { required: true, message: '请选择文章类型', trigger: 'blur' },
photo: { required: true, message: '请上传图片', trigger: 'blur' },
top: { required: true, message: '请选择是否置顶', trigger: 'blur' },
text: { required: true, message: '请输入文章内容', trigger: 'blur' },
},
2024-10-31 17:11:17 +08:00
fileArray:[],// 编辑进来时,如果已经上传了图片,则保存图片地址
2024-10-31 09:56:55 +08:00
coverFile: {},
coverHide: false
})
2024-10-31 17:11:17 +08:00
// 模块选择
const handleChangeModule = async(val: any) => {
try {
state.data.labelName = '';
if(!val){labelList.value=[]; return;}
const op:any = event?.currentTarget;
let res = await artApi.getLabelList(op.dataset.op);
if(res?.success){
labelList.value = res.data;
}else{
ElMessage.error('标签列表获取失败!');
}
} catch (error) {
ElMessage.error('标签列表获取失败!');
} finally {
}
}
2024-10-31 09:56:55 +08:00
// 获取文章详情
const getArticleDetail = async() => {
try {
state.loading = true;
let res = await artApi.getArticleList({
moduleName: moduleName,
labelName: labelName,
size: 1,
current: 1
});
if(res?.success) {
state.data = res.data.records[0];
// 下面这里处理一下因为后端返回的是0和1而前端需要的是true和false到时候提交的时候再转换回来
// 这个报错没关系的只是ts的语法检查不影响运行
state.data.top = state.data.top === 1;
2024-10-31 17:11:17 +08:00
state.data.textid = state.data.id;
if(state.data.photo){
const never:any = [{name:state.data.title,url:viteUrl+state.data.photo}];
state.fileArray = never;
state.coverHide = true;
}
2024-10-31 09:56:55 +08:00
}
} catch (error) {
ElMessage.error('获取文章详情失败');
} finally {
state.loading = false;
}
}
2024-11-12 17:35:06 +08:00
// 获取文章详情-根据id
const getArticleDetailById = async(id:number) => {
try {
state.loading = true;
let res = await artApi.getArticleDetail(id);
if(res?.success) {
state.data = res.data;
// 下面这里处理一下因为后端返回的是0和1而前端需要的是true和false到时候提交的时候再转换回来
// 这个报错没关系的只是ts的语法检查不影响运行
state.data.top = state.data.top === 1;
state.data.moduleName = moduleName;
state.data.labelName = labelName;
state.data.textid = state.data.id;
if(state.data.photo){
const never:any = [{name:state.data.title,url:viteUrl+state.data.photo}];
state.fileArray = never;
state.coverHide = true;
}
}
} catch (error) {
ElMessage.error('获取文章详情失败');
} finally {
state.loading = false;
}
}
2024-10-31 09:56:55 +08:00
// 获取模块列表
const getModuleList = async() => {
try {
let res = await artApi.getModuleList();
if(res?.success){
moduleList.value = res.data;
}else{
ElMessage.error('模块列表获取失败!');
}
} catch (error) {
ElMessage.error('模块列表获取失败!');
} finally {
}
}
const articleFormRef = ref();
// 保存文章
const onSubmitForm = () => {
articleFormRef.value.validate((valid: boolean) => {
2024-10-31 17:11:17 +08:00
if (valid && state.coverHide){
const form = {...state.data,top:state.data.top ? 1 : 0};
if(state.coverFile.type === undefined){
realSubmit(form);
}else{
uploadFile(state.coverFile,form);
}
}else{
ElMessage.error('请完善信息!');
}
2024-10-31 09:56:55 +08:00
});
};
2024-10-31 17:11:17 +08:00
// 返回
const cancel = () =>{
mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
router.push('/article');
}
// 上传文件
const uploadFile = async(file: any,form: any) => {
try {
state.loading = true;
const formdata = new FormData();
formdata.append('file', file);
console.log(file)
let res = await artApi.uploadFile(formdata);
if(res?.success){
form.photo = res.data.path;
realSubmit(form);
}else{
ElMessage.error('封面上传失败!');
}
} catch (error) {
state.loading = false;
ElMessage.error('封面上传失败!');
}
}
// 文章上传-真正的上传操作
const realSubmit = async(form: any) => {
try {
state.loading = true;
let res = route.path == '/article/add' ? await artApi.saveArticle(form) : await artApi.updateArticle(form);
if(res?.success){
ElMessage.success('文章保存成功!');
cancel();
}else{
ElMessage.error('文章保存失败!');
}
} catch (error) {
ElMessage.error('处理失败!');
} finally {
state.loading = false;
}
}
2024-10-31 09:56:55 +08:00
// 封面上传禁用
const disabled = ref(false);
// 封面弹窗
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const uploadRef = ref();
// 封面删除
const handleRemove = (file: UploadFile) => {
state.coverFile = {};
uploadRef.value.clearFiles();
2024-10-31 17:11:17 +08:00
state.coverHide = false;
2024-10-31 09:56:55 +08:00
}
// 封面预览
const handlePictureCardPreview = (file: UploadFile) => {
dialogImageUrl.value = file.url!
dialogVisible.value = true
}
// 封面下载
const handleDownload = (file: UploadFile) => {
2024-10-31 17:11:17 +08:00
console.log(file);
const fileUrl:any = file.url;
// window.location.href = fileUrl;
2024-10-31 09:56:55 +08:00
}
// 封面图片更改
const handleUploadChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
if(uploadFile.raw.type.includes('image')){
const file:any = uploadFile.raw;
state.coverFile = file;
state.coverHide = true;
}else{
ElMessage.error('请上传图片文件!');
uploadRef.value.clearFiles();
}
2024-10-31 09:56:55 +08:00
}
onMounted(() => {
2024-11-12 17:35:06 +08:00
if(moduleName && labelName && route.path == '/article/edit') {
if(moduleName && moduleName !== '人才模块' && moduleName !== '简历模块'){
getArticleDetailById(id);
}else{
getArticleDetail();
}
}
2024-10-31 09:56:55 +08:00
getModuleList();
})
</script>
<style scoped lang="scss">
.coverImg :deep(.hide .el-upload--picture-card) {
display: none;
}
</style>