完善文章管理
This commit is contained in:
parent
5a4d9181cb
commit
be2914146e
@ -11,6 +11,8 @@ import { baseUrlHost } from '../baseUrlHost';
|
||||
* @method getLabelList 获取标签列表
|
||||
* @method deleteArticle 删除文章
|
||||
* @method getArticleDetail 获取文章详情
|
||||
* @method saveArticle 保存文章
|
||||
* @method updateArticle 更新文章
|
||||
*/
|
||||
|
||||
export function articleApi() {
|
||||
@ -45,6 +47,28 @@ export function articleApi() {
|
||||
url: baseUrlHost + `/cpArticle/${id}`,
|
||||
method: 'get',
|
||||
});
|
||||
},
|
||||
saveArticle: (data: object) => {
|
||||
return request({
|
||||
url: baseUrlHost + '/cpArticle',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
},
|
||||
updateArticle: (data: object) => {
|
||||
return request({
|
||||
url: baseUrlHost + '/cpArticle',
|
||||
method: 'put',
|
||||
data,
|
||||
})
|
||||
},
|
||||
uploadFile: (data: object) => {
|
||||
return request({
|
||||
url: baseUrlHost + '/enAttachment/upload',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -7,9 +7,9 @@
|
||||
<el-form-item label="封面:">
|
||||
<el-image
|
||||
style="width: 100px;height: 100px;border-radius: 4px;"
|
||||
:src="state.data.photo"
|
||||
:src="encodeURI(viteUrl+state.data.photo)"
|
||||
:zoom-rate="1.2"
|
||||
:preview-src-list="[state.data.photo]"
|
||||
:preview-src-list="[encodeURI(viteUrl+state.data.photo)]"
|
||||
preview-teleported
|
||||
fit="cover"/>
|
||||
</el-form-item>
|
||||
@ -52,7 +52,15 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- <div class="mt5 mb20 ml10">文章内容:</div> -->
|
||||
<Editor v-model:get-html="state.data.text" v-model:get-text="state.data.text" :disable="true" />
|
||||
<Editor v-model:get-html="state.data.text" :disable="true" />
|
||||
<el-row class="flex mt15">
|
||||
<div class="flex-margin" style="width: 100%;display: flex;justify-content: flex-end;">
|
||||
<el-button size="larger" type="info" @click="cancel">
|
||||
<SvgIcon name="ele-RefreshLeft" />
|
||||
取消
|
||||
</el-button>
|
||||
</div>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
@ -61,12 +69,16 @@
|
||||
<script setup lang="ts" name="articleDetail">
|
||||
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
|
||||
import { articleApi } from '/@/api/article';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const Editor = defineAsyncComponent(() => import('/@/components/editor/index.vue'));
|
||||
|
||||
// 封面基本路径
|
||||
const viteUrl = import.meta.env.VITE_API_URL;
|
||||
|
||||
// 引入 api 请求接口
|
||||
const artApi = articleApi();
|
||||
|
||||
@ -75,6 +87,7 @@ const moduleList = ref([]);
|
||||
|
||||
// 获取模块名称和标签名称
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const moduleName:any = route.query.moduleName;
|
||||
const labelName:any = route.query.labelName;
|
||||
|
||||
@ -105,6 +118,7 @@ const getArticleDetail = async() => {
|
||||
});
|
||||
if(res?.success) {
|
||||
state.data = res.data.records[0];
|
||||
console.log(encodeURI(viteUrl+state.data.photo))
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取文章详情失败');
|
||||
@ -128,6 +142,12 @@ const getModuleList = async() => {
|
||||
}
|
||||
}
|
||||
|
||||
// 返回
|
||||
const cancel = () =>{
|
||||
mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
|
||||
router.push('/article');
|
||||
}
|
||||
|
||||
// 日期格式化
|
||||
function dateFormatter(){
|
||||
if(!state.data.createtime) return '';
|
||||
|
@ -6,8 +6,8 @@
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="封面:" class="coverImg">
|
||||
<!-- 上传文件 -->
|
||||
<el-upload ref="uploadRef" class="h100 personal-user-left-upload" action="#" list-type="picture-card"
|
||||
:auto-upload="false" :limit="1" :class="{ hide: state.coverHide }" @change="handleUploadChange">
|
||||
<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/*'>
|
||||
<template #default>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</template>
|
||||
@ -21,13 +21,13 @@
|
||||
>
|
||||
<el-icon><zoom-in /></el-icon>
|
||||
</span>
|
||||
<span
|
||||
<!-- <span
|
||||
v-if="!disabled"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleDownload(file)"
|
||||
>
|
||||
<el-icon><Download /></el-icon>
|
||||
</span>
|
||||
</span> -->
|
||||
<span
|
||||
v-if="!disabled"
|
||||
class="el-upload-list__item-delete"
|
||||
@ -43,14 +43,16 @@
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
<el-form-item label="模块名称:" prop="moduleName">
|
||||
<el-select size="default" v-model="state.data.moduleName" placeholder="请选择模块" clearable>
|
||||
<el-select size="default" @change="handleChangeModule" v-model="state.data.moduleName" placeholder="请选择模块" clearable>
|
||||
<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">
|
||||
<el-input v-model="state.data.labelName" placeholder="请输入标签名称" clearable></el-input>
|
||||
<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>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
|
||||
@ -72,10 +74,14 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item prop="text" label-width="0px">
|
||||
<Editor v-model:get-html="state.data.text" v-model:get-text="state.data.text" :disable="true" />
|
||||
<Editor v-model:get-html="state.data.text" :disable="true" />
|
||||
</el-form-item>
|
||||
<el-row class="flex mt15">
|
||||
<div class="flex-margin" style="width: 100%;display: flex;justify-content: flex-end;">
|
||||
<el-button size="larger" type="info" @click="cancel">
|
||||
<SvgIcon name="ele-RefreshLeft" />
|
||||
取消
|
||||
</el-button>
|
||||
<el-button size="larger" type="primary" @click="onSubmitForm">
|
||||
<SvgIcon name="iconfont icon-shuxing" />
|
||||
保存
|
||||
@ -94,21 +100,29 @@
|
||||
<script setup lang="ts" name="articleDetail">
|
||||
import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
|
||||
import { articleApi } from '/@/api/article';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { ElMessage, UploadFile, UploadFiles } from 'element-plus';
|
||||
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue'
|
||||
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue';
|
||||
import mittBus from '/@/utils/mitt';
|
||||
|
||||
// 引入组件
|
||||
const Editor = defineAsyncComponent(() => import('/@/components/editor/index.vue'));
|
||||
|
||||
// 封面基本路径
|
||||
const viteUrl = import.meta.env.VITE_API_URL;
|
||||
|
||||
// 引入 api 请求接口
|
||||
const artApi = articleApi();
|
||||
|
||||
// 模块列表
|
||||
const moduleList = ref([]);
|
||||
|
||||
// 标签列表
|
||||
const labelList = ref([]);
|
||||
|
||||
// 获取文章id
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const moduleName:any = route.query.moduleName;
|
||||
const labelName:any = route.query.labelName;
|
||||
|
||||
@ -133,10 +147,29 @@ const state = reactive({
|
||||
top: { required: true, message: '请选择是否置顶', trigger: 'blur' },
|
||||
text: { required: true, message: '请输入文章内容', trigger: 'blur' },
|
||||
},
|
||||
fileArray:[],// 编辑进来时,如果已经上传了图片,则保存图片地址
|
||||
coverFile: {},
|
||||
coverHide: false
|
||||
})
|
||||
|
||||
// 模块选择
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取文章详情
|
||||
const getArticleDetail = async() => {
|
||||
try {
|
||||
@ -152,6 +185,12 @@ const getArticleDetail = async() => {
|
||||
// 下面这里处理一下,因为后端返回的是0和1,而前端需要的是true和false,到时候提交的时候再转换回来
|
||||
// 这个报错没关系的,只是ts的语法检查,不影响运行
|
||||
state.data.top = state.data.top === 1;
|
||||
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('获取文章详情失败');
|
||||
@ -180,12 +219,63 @@ const articleFormRef = ref();
|
||||
// 保存文章
|
||||
const onSubmitForm = () => {
|
||||
articleFormRef.value.validate((valid: boolean) => {
|
||||
if (valid){
|
||||
|
||||
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('请完善信息!');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 返回
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 封面上传禁用
|
||||
const disabled = ref(false);
|
||||
// 封面弹窗
|
||||
@ -197,8 +287,8 @@ const uploadRef = ref();
|
||||
// 封面删除
|
||||
const handleRemove = (file: UploadFile) => {
|
||||
state.coverFile = {};
|
||||
state.coverHide = false;
|
||||
uploadRef.value.clearFiles();
|
||||
state.coverHide = false;
|
||||
}
|
||||
|
||||
// 封面预览
|
||||
@ -209,7 +299,9 @@ const handlePictureCardPreview = (file: UploadFile) => {
|
||||
|
||||
// 封面下载
|
||||
const handleDownload = (file: UploadFile) => {
|
||||
console.log(file)
|
||||
console.log(file);
|
||||
const fileUrl:any = file.url;
|
||||
// window.location.href = fileUrl;
|
||||
}
|
||||
|
||||
// 封面图片更改
|
||||
@ -217,11 +309,11 @@ const handleUploadChange = (uploadFile: UploadFile, uploadFiles: UploadFiles) =>
|
||||
const file:any = uploadFile.raw;
|
||||
state.coverFile = file;
|
||||
state.coverHide = true;
|
||||
console.log(uploadRef.value)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if(moduleName && labelName && route.path == '/article/edit')
|
||||
getArticleDetail();
|
||||
if(moduleName && labelName && route.path == '/article/edit') getArticleDetail();
|
||||
getModuleList();
|
||||
})
|
||||
|
||||
|
@ -36,6 +36,11 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/vueAdminApi/, ''),
|
||||
},
|
||||
'/upload': {
|
||||
target: 'http://8.138.171.103',
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
},
|
||||
'/gitee': {
|
||||
target: 'https://gitee.com',
|
||||
ws: true,
|
||||
|
Loading…
Reference in New Issue
Block a user