博客发布中,新增分类选择和封面上传,接入七牛云存储

This commit is contained in:
Xubx 2024-11-01 16:15:04 +08:00
parent 91d459b673
commit ff1fdabed2
4 changed files with 193 additions and 27 deletions

View File

@ -22,11 +22,13 @@
</div> </div>
<div class="right-nav"> <div class="right-nav">
<el-badge is-dot :hidden=isSignVisible> <el-badge is-dot :hidden=isSignVisible>
<el-dropdown @command="handleCommand" class="el-dropdown-link"> <el-dropdown class="el-dropdown-link">
<span> <span>
<el-avatar v-if="imageUrl" :src="imageUrl" style="width: 50px; height: 50px;" <router-link to="/personalHomapage" type="success" class="button-container">
class="avatar flip animated"></el-avatar> <el-avatar v-if="imageUrl" :src="imageUrl" style="width: 50px; height: 50px;"
<i v-else class="el-icon-plus avatar-uploader-icon"></i> class="avatar flip animated"></el-avatar>
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</router-link>
</span> </span>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<p>{{ this.username }}</p> <p>{{ this.username }}</p>
@ -36,8 +38,9 @@
</el-dropdown-item> </el-dropdown-item>
</a> </a>
<el-upload action="http://62.234.217.137:8088/user/uploadAvatar" :headers="uploadHeaders" :show-file-list="false" <el-upload action="http://62.234.217.137:8088/user/uploadAvatar" :headers="uploadHeaders"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"> :show-file-list="false" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<el-dropdown-item divided icon="el-icon-picture-outline-round">更换头像</el-dropdown-item> <el-dropdown-item divided icon="el-icon-picture-outline-round">更换头像</el-dropdown-item>
</el-upload> </el-upload>
<a @click="nameChangeVisible = true"> <a @click="nameChangeVisible = true">
@ -56,6 +59,12 @@
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</el-badge> </el-badge>
<router-link to="/add">
<el-button type="danger" round icon="el-icon-circle-plus-outline"
style="margin-left: 20px; font-size: 18px;">
发布
</el-button>
</router-link>
</div> </div>
</div> </div>
<el-dialog title="修改昵称" :modal="false" :visible="nameChangeVisible" width="400px" <el-dialog title="修改昵称" :modal="false" :visible="nameChangeVisible" width="400px"

2
src/config/ImageUrl.js Normal file
View File

@ -0,0 +1,2 @@
export const IMAGE_BASE_URL = "http://sm7c4t0ft.hb-bkt.clouddn.com/";
export const IMAGE_UPLOAD_URL = "http://sm7c4t0ft.hb-bkt.clouddn.com/";

View File

@ -1,9 +1,9 @@
<template> <template>
<div> <div class="m_content">
<!-- 引用导航 --> <!-- 引用导航 -->
<AddHeader></AddHeader> <Menu></Menu>
<br> <br>
<div class="m_content"> <div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="标题" prop="title"> <el-form-item label="标题" prop="title">
<el-input v-model="ruleForm.title"></el-input> <el-input v-model="ruleForm.title"></el-input>
@ -17,10 +17,54 @@
<!-- 特殊组件 --> <!-- 特殊组件 -->
<mavon-editor v-model="ruleForm.content"></mavon-editor> <mavon-editor v-model="ruleForm.content"></mavon-editor>
</el-form-item> </el-form-item>
<el-form-item prop="cover">
<el-card>
<el-row style="display: flex; align-items: center;">
<el-col :span="3">
<p>
<span style="color: red">*</span>
文章分类
</p>
</el-col>
<el-col :span="16" style="display: flex; flex-wrap: wrap;">
<el-popover trigger="hover" style="float: left;" placement="bottom" width="300">
<el-checkbox-group v-model="selectedTags">
<el-checkbox v-for="tag in tags" :label="tag.id" :key="tag.id"
@change="handleClick(tag)">
{{ tag.name }}
</el-checkbox>
</el-checkbox-group>
<el-button icon="el-icon-plus" slot="reference">添加文章标签</el-button>
</el-popover>
<div v-for="selectedTag in selectedTags" :key="selectedTag">
<el-tag style="margin-left: 3px;" :closable="true"
@close="handleClose(selectedTag)">
{{ tags.find(t => t.id === selectedTag).name }}
</el-tag>
</div>
</el-col>
</el-row>
<el-row style="display: flex; align-items: center;">
<el-col :span="3">
<p>
添加封面
</p>
</el-col>
<el-col :span="16" style="display: flex; flex-wrap: wrap;">
<el-upload class="cover-uploader" action="http://up-z1.qiniup.com"
:headers="uploadHeaders" :show-file-list="false" :on-success="handleCoverSuccess"
:before-upload="beforeCoverUpload" :data="uploadData">
<img v-if="imageUrl" :src="imageUrl" class="cover">
<i v-else class="el-icon-plus cover-uploader-icon"></i>
</el-upload>
</el-col>
</el-row>
</el-card>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">立即发布</el-button> <el-button type="primary" @click="submitForm('ruleForm')">立即发布</el-button>
<!-- <el-button @click="resetForm('ruleForm')">重置</el-button> --> <!-- <el-button s@click="resetForm('ruleForm')">重置</el-button> -->
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@ -32,11 +76,11 @@
<script> <script>
import axios from 'axios'; import axios from 'axios';
import AddHeader from "../components/AddHeader";
import Footer from "../components/Footer"; import Footer from "../components/Footer";
import Menu from '../components/Menu.vue'
export default { export default {
components: {AddHeader, Footer}, components: { Footer, Menu },
beforeRouteEnter(to, from, next) { beforeRouteEnter(to, from, next) {
// //
window.scrollTo(0, 0); window.scrollTo(0, 0);
@ -44,6 +88,35 @@ export default {
}, },
data() { data() {
return { return {
tags: [{
id: 1,
name: "Java"
}, {
id: 2,
name: "Python"
},
{
id: 3,
name: "Vue"
},
{
id: 4,
name: "Spring"
},
{
id: 5,
name: "Linux"
},
{
id: 6,
name: "MySQL"
},
],
selectedTags: [],
imageUrl: '',
imageKey: '',
uploadData: { key: "", token: "" },
form: {},
ruleForm: { ruleForm: {
id: "", id: "",
title: "", title: "",
@ -74,11 +147,12 @@ export default {
if (valid) { if (valid) {
// //
axios.post('/blog/addBlog', { axios.post('/blog/addBlog', {
// id: this.ruleForm.id,
title: this.ruleForm.title, title: this.ruleForm.title,
description: this.ruleForm.description, description: this.ruleForm.description,
categories: this.selectedTags,
content: this.ruleForm.content, content: this.ruleForm.content,
created: new Date() coverImage: this.imageKey,
status: '草稿'
}).then(function (response) { }).then(function (response) {
console.log(response.data) console.log(response.data)
// //
@ -93,8 +167,53 @@ export default {
resetForm(formName) { resetForm(formName) {
console.log(formName) console.log(formName)
this.$refs[formName].resetFields();//Element, this.$refs[formName].resetFields();//Element,
},
handleClose(tagId) {
this.selectedTags = this.selectedTags.filter(t => t !== tagId);
},
handleClick(tag) {
if (!this.selectedTags.includes(tag.id)) {
this.selectedTags.push(tag.id);
}
},
handleCoverSuccess(res, file) {
console.log(res)
this.imageKey = res.key;
this.imageUrl = URL.createObjectURL(file.raw);
console.log("图片路径:", this.imageUrl)
},
beforeCoverUpload(file) {
//
axios.get('/upload/getUploadCredentials').then((res) => {
if (res.status === 200) {
this.uploadData.key = file.uid + file.name
this.uploadData.token = res.data
console.log(this.uploadData)
} else {
this.uploadData.key = "";
this.uploadData.token = "";
console.log('获取上传凭证失败')
}
})
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJPG) {
this.$message.error('上传图片只能是 JPG/PNG 格式!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$message.error('上传图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
}
},
computed: {
uploadHeaders() {
// localStoragetoken
const token = window.localStorage.getItem("token");
return {
Authorization: token ? token : ''
};
} }
}, },
@ -103,9 +222,44 @@ export default {
</script> </script>
<style> <style>
.m_content { .m_content {
margin: 0 auto; margin: 0 auto;
background: #e6e6e6;
}
.demo-ruleForm {
margin: 0 auto;
width: 80%;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.01);
}
.cover-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.cover-uploader .el-upload:hover {
border-color: #409EFF;
}
.cover-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 150px;
height: 150px;
line-height: 150px;
text-align: center;
}
.cover {
width: 150px;
height: 150px;
display: block;
} }
</style> </style>

View File

@ -8,16 +8,17 @@
<div class="live2d-container"> <div class="live2d-container">
<el-col :span="1"> <el-col :span="1">
<live2d style="position: absolute; left: 0; bottom: 0;" <live2d style="position: absolute; left: 0; bottom: 0;"
:model="['Potion-Maker/Pio', 'school-2017-costume-yellow']" :direction="direction" :size="size"> :model="['Potion-Maker/Pio', 'school-2017-costume-yellow']" :direction="direction"
:size="size">
</live2d> </live2d>
</el-col> </el-col>
</div> </div>
<el-col :span="23"> <el-col :span="23">
<el-card :body-style="{ padding: '0px' }" v-for="blog in pagedBlogs" style="margin-bottom: 20px;" <el-card :body-style="{ padding: '0px' }" v-for="blog in pagedBlogs" style="margin-bottom: 20px;"
:key="blog.id"> :key="blog.id">
<el-col :span="12"> <el-col :span="12">
<router-link :to="{ name: 'BlogDetail', params: { blogId: blog.id } }"> <router-link :to="{ name: 'BlogDetail', params: { blogId: blog.id } }">
<img :src="blog.imageUrl" class="pulse animated image" /> <img :src="blog.coverImage" class="pulse animated image" :data="blog.id" />
</router-link> </router-link>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -55,6 +56,8 @@ import Footer from "../components/Footer";
// //
import live2d from 'vue-live2d' import live2d from 'vue-live2d'
import { startSakura } from "../js/Sakura" import { startSakura } from "../js/Sakura"
import { IMAGE_BASE_URL } from "../config/ImageUrl";
export default { export default {
components: { components: {
HomeHeader, HomeHeader,
@ -117,8 +120,8 @@ export default {
axios.get("/blog/getBlogs").then((response) => { axios.get("/blog/getBlogs").then((response) => {
that.blogs = response.data; that.blogs = response.data;
for (let index in that.blogs) { for (let index in that.blogs) {
that.blogs[index].imageUrl = this.imageUrls[index % 8]; that.blogs[index].coverImage = IMAGE_BASE_URL + that.blogs[index].coverImage;
console.log(that.blogs[index].imageUrl); console.log(that.blogs[index].coverImage);
} }
that.total = that.blogs.length; // that.total = that.blogs.length; //
that.handleCurrentChange(that.currentPage); // that.handleCurrentChange(that.currentPage); //
@ -128,10 +131,8 @@ export default {
const startIndex = (page - 1) * this.pageSize; // const startIndex = (page - 1) * this.pageSize; //
const endIndex = startIndex + this.pageSize; // const endIndex = startIndex + this.pageSize; //
this.pagedBlogs = this.blogs.slice(startIndex, endIndex); // this.pagedBlogs = this.blogs.slice(startIndex, endIndex); //
}, },
show() { show() {
!function () { !function () {
function n(n, e, t) { function n(n, e, t) {