完善文章管理

This commit is contained in:
Double-_-Z 2024-10-31 17:11:17 +08:00
parent 5a4d9181cb
commit be2914146e
4 changed files with 161 additions and 20 deletions

View File

@ -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'}
})
}
};
}

View File

@ -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 '';

View File

@ -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() => {
// 01truefalse
// 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();
})

View File

@ -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,