blog機能完成

This commit is contained in:
simple321vip
2022-05-02 22:10:20 +08:00
parent 91ee8a9577
commit 0a2c848fa0
10 changed files with 254 additions and 80 deletions
+3 -3
View File
@@ -365,8 +365,8 @@
"dev": true "dev": true
}, },
"async": { "async": {
"version": "2.6.3", "version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
"requires": { "requires": {
"lodash": "^4.17.14" "lodash": "^4.17.14"
@@ -1250,7 +1250,7 @@
"resolved": "https://registry.npmjs.org/save/-/save-2.4.0.tgz", "resolved": "https://registry.npmjs.org/save/-/save-2.4.0.tgz",
"integrity": "sha512-wd5L2uVnsKYkIUaK6i8Ie66IOHaI328gMF0MPuTJtYOjXgUolC33LSIk7Qr8WVA55QHaGwfiVS8a7EFIeGOR3w==", "integrity": "sha512-wd5L2uVnsKYkIUaK6i8Ie66IOHaI328gMF0MPuTJtYOjXgUolC33LSIk7Qr8WVA55QHaGwfiVS8a7EFIeGOR3w==",
"requires": { "requires": {
"async": "^2.6.2", "async": "^2.6.4",
"event-stream": "^4.0.1", "event-stream": "^4.0.1",
"lodash.assign": "^4.2.0", "lodash.assign": "^4.2.0",
"mingo": "1" "mingo": "1"
+11 -13
View File
@@ -1,19 +1,8 @@
import request from '../utils/request' import request from '../utils/request'
import Qs from 'qs'
const headers = { const headers = {
'Content-Type': 'application/json;charsetset=UTF-8' 'Content-Type': 'application/json;charsetset=UTF-8'
} }
const get_blogs = (params: Object) => {
return request({
url: '/blog',
method: 'GET',
params: params,
paramsSerializer: (params) => {
return Qs.stringify(params, { arrayFormat: 'repeat' })
},
})
}
const listAll = () => { const listAll = () => {
return request({ return request({
@@ -40,6 +29,15 @@ const putBlogType = (data: Object) => {
}) })
} }
const removeBlogType = (data: Object) => {
return request({
url: '/author/blog_type',
method: 'DELETE',
headers: headers,
data: data
})
}
const getContent = (id: string) => { const getContent = (id: string) => {
return request({ return request({
url: '/author/blog/content/' + id, url: '/author/blog/content/' + id,
@@ -68,11 +66,11 @@ const updateContent = (postData: Object) => {
const deleteContent = (bid: string) => { const deleteContent = (bid: string) => {
return request({ return request({
url: '/author/blog/content/' + bid, url: '/author/blog/' + bid,
method: 'DELETE', method: 'DELETE',
headers: headers, headers: headers,
}) })
} }
export { get_blogs, listAll, updateBtName, putBlogType, getContent, putBlog, updateContent, deleteContent } export { listAll, updateBtName, putBlogType, removeBlogType, getContent, putBlog, updateContent, deleteContent }
+35
View File
@@ -0,0 +1,35 @@
import request from '../utils/request'
import Qs from 'qs'
const headers = {
'Content-Type': 'application/json;charsetset=UTF-8'
}
const getBlogs = (params: Object) => {
return request({
url: '/reader/blogs',
method: 'GET',
params: params,
paramsSerializer: (params) => {
return Qs.stringify(params, { arrayFormat: 'repeat' })
},
})
}
const getBtName = () => {
return request({
url: '/reader/blog_type',
method: 'GET',
headers: headers
})
}
const getBlog = (bid: string) => {
return request({
url: '/reader/blog/' + bid,
method: 'GET',
headers: headers
})
}
export { getBlogs, getBlog, getBtName }
-2
View File
@@ -29,8 +29,6 @@
import MainApp from '../layout/MainApp.vue'; import MainApp from '../layout/MainApp.vue';
import NavBar from "../layout/NavBar.vue"; import NavBar from "../layout/NavBar.vue";
import SideBar from "../layout/SideBar.vue"; import SideBar from "../layout/SideBar.vue";
console.log(window.innerHeight)
</script> </script>
<style scoped> <style scoped>
+1 -1
View File
@@ -1,6 +1,6 @@
<template> <template>
<section class="section-main" style="height:100%;"> <section class="section-main" style="height:100%;">
<router-view style="height:100%;" /> <router-view />
</section> </section>
</template> </template>
+9
View File
@@ -14,6 +14,7 @@ app.use(ElementPlus)
app.use(store) app.use(store)
import { getToken, getUser } from './utils/auth' import { getToken, getUser } from './utils/auth'
import { User } from './entity/index' import { User } from './entity/index'
import Cookies from 'js-cookie';
const whiteList = ['/login'] const whiteList = ['/login']
let url = window.location.href let url = window.location.href
@@ -40,6 +41,14 @@ router.beforeEach((to, from, next) => {
const user = <User>(JSON.parse(getUser() as string)) const user = <User>(JSON.parse(getUser() as string))
if (url.search("write") != -1) { if (url.search("write") != -1) {
next('/BlogEditer') next('/BlogEditer')
} else if (url.search("view") != -1) {
let bid = Cookies.get('bid')
router.push({
path: '/BlogViewer',
query: { bid: bid }
})
// next('/BlogViewer')
console.log(1)
} else { } else {
router.push({ router.push({
path: '/home', path: '/home',
+4
View File
@@ -71,6 +71,10 @@ const routes: Array<RouteRecordRaw> = [
path: "/BlogEditer", path: "/BlogEditer",
component: () => import('../view/blog/createBlog.vue') component: () => import('../view/blog/createBlog.vue')
}, },
{
path: "/BlogViewer",
component: () => import('../view/blog/mdview.vue')
},
{ {
path: "/login", path: "/login",
component: () => import('../components/login/login.vue') component: () => import('../components/login/login.vue')
+99 -9
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="blog_editer" v-if="isReady"> <div class="blog_editer" v-if="isReady">
<div class="bt_section" :style="btWholeStyle"> <div class="bt_section" :style="btWholeStyle">
<el-button class="bt-input" @click="contentDialogVisible = true">增加</el-button> <el-button class="bt-input" @click="contentDialogVisible = true">增加一个分类</el-button>
<el-button class="bt-input" v-for="(value, key) of blogTypes" :key="key" @click="onclickTypeTab(value[0])"> <el-button class="bt-input" v-for="(value, key) of blogTypes" :key="key" @click="onclickTypeTab(value[0])">
<el-dropdown trigger="click"> <el-dropdown trigger="click">
<el-icon v-show="checkedBlogIndex == value[0]"> <el-icon v-show="checkedBlogIndex == value[0]">
@@ -19,9 +19,21 @@
</el-button> </el-button>
</div> </div>
<div class="b_section" :style="bWholeStyle"> <div class="b_section" :style="bWholeStyle">
<el-button class="bt-input" @click="insertBlog">增加</el-button> <el-button class="bt-input" :disabled="isclicked" @click="insertBlog">增加一个博客</el-button>
<el-button class="bt-input" v-for="(blog, index) of blogTypes.get(checkedBlogIndex)?.blogs" <el-button class="bt-input" v-for="(blog, index) of blogTypes.get(checkedBlogIndex)?.blogs"
@click="onclickBlogTab(blog[0])"> @click="onclickBlogTab(blog[0])">
<el-dropdown trigger="click">
<el-icon v-show="checkedIndex == blog[0]">
<edit />
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="deleteDialogVisible = true">删除</el-dropdown-item>
<el-dropdown-item>顶置</el-dropdown-item>
<el-dropdown-item @click="true">退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
{{ blog[1].title }} {{ blog[1].title }}
</el-button> </el-button>
</div> </div>
@@ -30,6 +42,10 @@
<el-input v-model="((blogTypes.get(checkedBlogIndex) as BlogType).blogs.get(checkedIndex) as Blog).title" <el-input v-model="((blogTypes.get(checkedBlogIndex) as BlogType).blogs.get(checkedIndex) as Blog).title"
@keyup.enter.native="saveTitle" @blur="saveTitle"> @keyup.enter.native="saveTitle" @blur="saveTitle">
</el-input> </el-input>
<div style="width: 60px;">
<span v-if="!updated">已保存</span>
<span v-if="updated">更新中</span>
</div>
</div> </div>
<div :style="cWholeStyle"> <div :style="cWholeStyle">
<md-editor theme="light" <md-editor theme="light"
@@ -63,7 +79,18 @@
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="btdeleteDialogVisible = false">取消</el-button> <el-button @click="btdeleteDialogVisible = false">取消</el-button>
<el-button type="primary" @click="insertBlogType">确认</el-button> <el-button type="primary" @click="deleteBlogType">确认</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="deleteDialogVisible" title="删除博客" width="30%">
你正在对 {{ ((blogTypes.get(checkedBlogIndex) as BlogType).blogs.get(checkedIndex) as Blog).title }}
<el-input v-model="btName" :placeholder="'请输入<删除>'">
</el-input>
<template #footer>
<span class="dialog-footer">
<el-button @click="deleteDialogVisible = false">取消</el-button>
<el-button type="primary" @click="deleteBlog">确认</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
@@ -75,7 +102,7 @@ import { onMounted, reactive, ref } from 'vue'
import MdEditor from 'md-editor-v3' import MdEditor from 'md-editor-v3'
import { Edit } from "@element-plus/icons-vue"; import { Edit } from "@element-plus/icons-vue";
import 'md-editor-v3/lib/style.css' import 'md-editor-v3/lib/style.css'
import { updateBtName, updateContent, listAll, putBlogType, getContent, putBlog } from '../../api/blog' import { updateBtName, updateContent, listAll, putBlogType, removeBlogType, getContent, putBlog, deleteContent } from '../../api/blog'
import $moment from "moment"; import $moment from "moment";
type Blog = { type Blog = {
@@ -96,10 +123,13 @@ const blogTypes = reactive<Map<string, BlogType>>(new Map())
const dialogVisible = ref(false) const dialogVisible = ref(false)
const contentDialogVisible = ref(false) const contentDialogVisible = ref(false)
const btdeleteDialogVisible = ref(false) const btdeleteDialogVisible = ref(false)
const deleteDialogVisible = ref(false)
let checkedIndex = ref<string>("") let checkedIndex = ref<string>("")
let checkedBlogIndex = ref<string>("") let checkedBlogIndex = ref<string>("")
let isclicked = ref(false)
let isReady = ref(false) let isReady = ref(false)
let updated = ref(false)
// 関数定義 // 関数定義
@@ -114,7 +144,6 @@ const getTestData = async () => {
btName: element.btName, btName: element.btName,
blogs: new Map<string, Blog>() blogs: new Map<string, Blog>()
} }
blogTypes.set(element.btId, blog_type)
element.blog_list.forEach((item: any) => { element.blog_list.forEach((item: any) => {
const blog: Blog = { const blog: Blog = {
bid: item.bid, bid: item.bid,
@@ -126,6 +155,7 @@ const getTestData = async () => {
} }
blog_type.blogs.set(item.bid, blog) blog_type.blogs.set(item.bid, blog)
}) })
blogTypes.set(element.btId, blog_type)
}) })
}) })
isReady.value = true isReady.value = true
@@ -148,6 +178,12 @@ const onclickTypeTab = (key: string) => {
} }
const onclickBlogTab = (key: string) => { const onclickBlogTab = (key: string) => {
checkedIndex.value = key checkedIndex.value = key
getContent(key).then(response => {
((blogTypes.get(checkedBlogIndex.value) as BlogType).blogs.get(checkedIndex.value) as Blog).content = response.data.content
})
} }
const handleEditBtName = (bt: BlogType) => { const handleEditBtName = (bt: BlogType) => {
dialogVisible.value = true dialogVisible.value = true
@@ -186,13 +222,16 @@ const saveContent = () => {
content: ((blogTypes.get(checkedBlogIndex.value) as BlogType).blogs.get(checkedIndex.value) as Blog).content content: ((blogTypes.get(checkedBlogIndex.value) as BlogType).blogs.get(checkedIndex.value) as Blog).content
} }
updateContent(query).then(response => { updateContent(query).then(response => {
if (response.status == 200) {
// blogTypes.get(checkedBlogIndex.value)?.blogs.get(checkedIndex.value)?.content =
}
}) })
} }
/** /**
* ブログ新規作成 * ブログ新規作成
*/ */
const insertBlog = () => { const insertBlog = () => {
isclicked.value = true
const data = { const data = {
btId: checkedBlogIndex.value, btId: checkedBlogIndex.value,
title: $moment().format("YYYY-MM-DD") title: $moment().format("YYYY-MM-DD")
@@ -209,8 +248,27 @@ const insertBlog = () => {
} as Blog } as Blog
(blogTypes.get(checkedBlogIndex.value) as BlogType).blogs.set(bid, blog) (blogTypes.get(checkedBlogIndex.value) as BlogType).blogs.set(bid, blog)
checkedIndex.value = bid checkedIndex.value = bid
isclicked.value = false
}) })
} }
/**
* ブログ削除
*/
const deleteBlog = () => {
if (btName.value == "删除") {
deleteContent(checkedIndex.value).then(response => {
if (response.status == 200) {
const deleteKey = checkedIndex.value
checkedIndex.value = blogTypes.get(checkedBlogIndex.value)?.blogs.keys().next().value
blogTypes.get(checkedBlogIndex.value)?.blogs.delete(deleteKey)
deleteDialogVisible.value = false
}
})
btName.value = ""
}
}
// Blogタイプ新規作成用、作成後、リセットする // Blogタイプ新規作成用、作成後、リセットする
let btName = ref("") let btName = ref("")
const insertBlogType = () => { const insertBlogType = () => {
@@ -223,7 +281,6 @@ const insertBlogType = () => {
btName: response.data.btName, btName: response.data.btName,
blogs: new Map<string, Blog>() blogs: new Map<string, Blog>()
} }
blogTypes.set(response.data.btId, blog_type)
response.data.blog_list.forEach((item: any) => { response.data.blog_list.forEach((item: any) => {
const blog: Blog = { const blog: Blog = {
bid: item.bid, bid: item.bid,
@@ -235,12 +292,34 @@ const insertBlogType = () => {
} }
blog_type.blogs.set(item.bid, blog) blog_type.blogs.set(item.bid, blog)
}) })
blogTypes.set(response.data.btId, blog_type)
checkedBlogIndex.value = response.data.btId
checkedIndex.value = blog_type.blogs.keys().next().value
contentDialogVisible.value = false contentDialogVisible.value = false
btName.value = "" btName.value = ""
}) })
} }
const deleteBlogType = () => { const deleteBlogType = () => {
if (btName.value == (blogTypes.get(checkedBlogIndex.value) as BlogType).btName) {
const data = {
btId: checkedBlogIndex.value
}
removeBlogType(data).then((response) => {
if (response.status == 200) {
blogTypes.delete(checkedBlogIndex.value)
checkedBlogIndex.value = blogTypes.keys().next().value
checkedIndex.value = blogTypes.values().next().value.blogs.keys().next().value
} else {
}
btdeleteDialogVisible.value = false
})
btName.value = ""
} else {
}
} }
@@ -281,8 +360,6 @@ onMounted(() => {
border-right: 1px solid royalblue; border-right: 1px solid royalblue;
} }
.bt-input { .bt-input {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -294,11 +371,24 @@ onMounted(() => {
height: 50px; height: 50px;
border-radius: 0px; border-radius: 0px;
border-right: 0px; border-right: 0px;
border-left: 0px;
border-top: 1px solid royalblue;
border-bottom: 1px solid royalblue;
}
.title_style {
display: flex;
} }
.title_style :deep() .el-input__inner { .title_style :deep() .el-input__inner {
flex-direction: row;
height: 50px; height: 50px;
font-size: 20px; font-size: 20px;
border-right: 0px;
border-left: 0px;
border-radius: 0px;
border-top: 1px solid royalblue;
border-bottom: 1px solid royalblue;
} }
.el-dropdown { .el-dropdown {
+83 -47
View File
@@ -1,21 +1,47 @@
<template> <template>
<el-button @click="openBlogEditer">进入博客小作坊</el-button> <el-form :model="form" label-width="120px">
<el-button @click="test">获取博客内容</el-button> <el-form-item label="关键字搜索">
<el-button @click="test1">新增博客</el-button> <el-col :span="7">
<el-button @click="test2">更新博客</el-button> <el-input v-model="form.key_word" />
<el-button @click="test3">削除博客</el-button> </el-col>
<el-col :span="1"></el-col>
<el-col :span="10">
<span>分类搜索</span>
<el-select v-model="form.btId" placeholder="选择分类">
<el-option v-for="item in btNameList" :key="item.btId" :label="item.btName" :value="item.btId" />
</el-select>
</el-col>
</el-form-item>
<el-form-item label="创作时间">
<el-col :span="7">
<el-date-picker v-model="form.start_day" type="date" placeholder="开始时间" style="width: 100%" />
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="7">
<el-time-picker v-model="form.end_day" placeholder="结束时间" style="width: 100%" />
</el-col>
<el-col :span="6" style="text-align: center;">
<el-button type="primary" @click="onSubmit">搜索</el-button>
</el-col>
</el-form-item>
</el-form>
<el-button @click="openBlogEditer">创作</el-button>
<div class="blog_list" v-for="item in data_list"> <div class="blog_list" v-for="item in data_list">
<h3 style="cursor: pointer;" @click="openBlog">{{ item.title }}</h3> <h3 style="cursor: pointer; width: min-content;white-space:nowrap" @click="openBlog(item.bid)">{{ item.title }}</h3>
<span style="font-size: 12px;">{{ item.blog_prex }}</span> <span style="font-size: 12px;">{{ item.bid }}</span>
<!-- <span style="font-size: 12px;">{{ item.blog_prex }}</span> -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue'; import Cookies from 'js-cookie';
import { get_blogs, getContent, putBlog, updateContent, deleteContent } from '../../api/blog' import { reactive } from 'vue';
import { getBlogs, getBtName } from '../../api/blogView'
import router from '../../router/index' import router from '../../router/index'
type Blog = { type Blog = {
bid: string, bid: string,
@@ -25,23 +51,58 @@ type Blog = {
blog_prex: string, blog_prex: string,
content: string content: string
} }
const data_list = reactive<Blog[]>([]) type Blog_Type = {
btId: string,
btName: string
}
const query = () => { // 変数定義
get_blogs(1).then(response => { const form = reactive({
key_word: '',
btId: '',
start_day: '',
end_day: ''
})
const data_list = reactive<Blog[]>([])
const btNameList = reactive<Blog_Type[]>([])
// 関数定義
const init = () => {
getBlogs({}).then(response => {
response.data.forEach((item: Blog) => { response.data.forEach((item: Blog) => {
data_list.push(item) data_list.push(item)
}); })
})
getBtName().then(response => {
btNameList.push({ btId: "", btName: "选择分类" })
response.data.forEach((item: any) => {
const bts = {
btId: item.btId,
btName: item.btName
}
btNameList.push(bts)
})
}) })
} }
query()
let text = ref<string>('')
text.value = "开始吧肿瘤"
const openBlog = () => { const onSubmit = () => {
getBlogs(form).then(response => {
data_list.splice(0, data_list.length);
response.data.forEach((item: Blog) => {
data_list.push(item)
})
})
}
const openBlog = (bid: string) => {
Cookies.set('bid', bid)
const { href } = router.resolve({ const { href } = router.resolve({
path: '/blog=1' path: '/view',
query: {
bid: bid
}
}); });
window.open(href, '_blank'); window.open(href, '_blank');
} }
@@ -52,36 +113,11 @@ const openBlogEditer = () => {
}); });
window.open(href, '_blank'); window.open(href, '_blank');
} }
const test = () => {
getContent('123456').then(response => {
console.log(response)
})
}
const test1 = () => {
const params = {
blog_type_id: "2808000",
title: "dddddddd"
}
putBlog(params).then(response => {
console.log(response)
})
}
const test2 = () => {
const params = {
bid: "22222",
title: "22222222222",
content: "dddddddddddddddddddddddddddd"
}
updateContent(params).then(response => {
console.log(response)
})
}
const test3 = () => {
deleteContent('22222').then(response => { // 初期化処理
console.log(response) init()
})
}
</script> </script>
<style> <style>
+8 -4
View File
@@ -7,13 +7,17 @@ import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css'; import 'md-editor-v3/lib/style.css';
import { ref } from 'vue'; import { ref } from 'vue';
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
// import { get_blog } from '../../api/blog' import { getBlog } from '../../api/blogView'
let text = ref<string>('') let text = ref<string>('')
const route = useRoute() const route = useRoute()
// get_blog(route.query).then(response => { const params = route.query
// text.value = response.data.blog_text
// })
const init = () => {
getBlog(params.bid as string).then(response => {
text.value = response.data.content
})
}
init()
</script> </script>
<style> <style>