parent
7f08beda6d
commit
dfff087598
16 changed files with 545 additions and 130 deletions
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -1,22 +1,113 @@ |
||||
<template> |
||||
<div id="header"> |
||||
<div class="grid"> |
||||
<div></div> |
||||
<h1>My Drf-Vue Blog</h1> |
||||
<div class="search"> |
||||
<form> |
||||
<input v-model="searchText" type="text" placeholder="输入搜索内容..." /> |
||||
<button v-on:click.prevent="searchArticles"> |
||||
</button> |
||||
</form> |
||||
</div> |
||||
<hr> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { ref } from "vue" |
||||
import router from '@/router/index'; |
||||
|
||||
export default { |
||||
name: "BlogHeader", |
||||
setup() { |
||||
let searchText = ref(''); |
||||
|
||||
const searchArticles = () => { |
||||
const text = searchText.value.trim(); |
||||
if (text.charAt(0) !== '') { |
||||
router.push({name:'home', query: {search: text }}) |
||||
} |
||||
} |
||||
|
||||
return { |
||||
searchText, |
||||
searchArticles, |
||||
} |
||||
|
||||
} |
||||
|
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
|
||||
#header { |
||||
text-align: center; |
||||
margin-top: 20px; |
||||
} |
||||
.grid { |
||||
display: grid; |
||||
grid-template-columns: 1fr 4fr 1fr; |
||||
} |
||||
|
||||
.search { |
||||
padding-top: 22px; |
||||
} |
||||
|
||||
/* 搜索框样式 */ |
||||
* { |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
form { |
||||
position: relative; |
||||
width: 20vw; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
input, |
||||
button { |
||||
outline: none; |
||||
} |
||||
|
||||
input { |
||||
border-color: gray; |
||||
width: 100%; |
||||
height: 30px; |
||||
padding-left: 13px; |
||||
padding-right: 46px; |
||||
overflow:hidden; |
||||
text-overflow:ellipsis; |
||||
} |
||||
|
||||
button { |
||||
border: none; |
||||
height: 30px; |
||||
width: 30px; |
||||
cursor: pointer; |
||||
position: absolute; |
||||
} |
||||
|
||||
.search input { |
||||
border: 2px solid gray; |
||||
border-radius: 5px; |
||||
background: transparent; |
||||
top: 0; |
||||
right: 0; |
||||
} |
||||
|
||||
.search button { |
||||
background: gray; |
||||
border-radius: 0 5px 5px 0; |
||||
width: 45px; |
||||
top: 0; |
||||
right: 0; |
||||
} |
||||
|
||||
.search button:before { |
||||
content: "搜索"; |
||||
font-size: 13px; |
||||
color: white; |
||||
} |
||||
</style> |
||||
|
@ -1,4 +1,13 @@ |
||||
import { createApp } from 'vue' |
||||
import App from './App.vue' |
||||
import router from './router' |
||||
import store from './store' |
||||
|
||||
createApp(App).mount('#app') |
||||
URLSearchParams.prototype.appendIfExists = function (key, value) { |
||||
if (value !== null && value !== undefined) { |
||||
this.append(key, value) |
||||
} |
||||
}; |
||||
|
||||
|
||||
createApp(App).use(store).use(router).mount('#app') |
||||
|
@ -0,0 +1,23 @@ |
||||
import { createRouter, createWebHistory } from 'vue-router' |
||||
import HomePage from '@/views/HomePageView.vue' |
||||
import ArticleDetail from '@/views/ArticleDetailView.vue' |
||||
|
||||
const routes = [ |
||||
{ |
||||
path: '/', |
||||
name: 'home', |
||||
component: HomePage |
||||
}, |
||||
{ |
||||
path: '/detail/:id', |
||||
name: 'detail', |
||||
component: ArticleDetail, |
||||
}, |
||||
] |
||||
|
||||
const router = createRouter({ |
||||
history: createWebHistory(), // 路径中不再有恶心的#号
|
||||
routes |
||||
}) |
||||
|
||||
export default router |
@ -0,0 +1,14 @@ |
||||
import { createStore } from 'vuex' |
||||
|
||||
export default createStore({ |
||||
state: { |
||||
}, |
||||
getters: { |
||||
}, |
||||
mutations: { |
||||
}, |
||||
actions: { |
||||
}, |
||||
modules: { |
||||
} |
||||
}) |
@ -0,0 +1,5 @@ |
||||
<template> |
||||
<div class="about"> |
||||
<h1>This is an about page</h1> |
||||
</div> |
||||
</template> |
@ -0,0 +1,95 @@ |
||||
<template> |
||||
<BlogHeader /> |
||||
<div v-if="article !== null" class="grid-container"> |
||||
<div> |
||||
<h1 id='title'>{{article.title}}</h1> |
||||
<p id="subtitle"> |
||||
本文由{{article.author.username}} 发布于 {{formatted_time(article.created)}} |
||||
</p> |
||||
<div v-html='article.body_html' class="article-body"> |
||||
</div> |
||||
</div> |
||||
|
||||
<div> |
||||
<h3>目录</h3> |
||||
<div v-html='article.toc_html' class="toc"></div> |
||||
</div> |
||||
</div> |
||||
<BlogFooter /> |
||||
</template> |
||||
|
||||
<script> |
||||
import BlogHeader from "@/components/BlogHeader.vue"; |
||||
import BlogFooter from "@/components/BlogFooter.vue"; |
||||
import $ from 'jquery'; |
||||
import { ref } from 'vue'; |
||||
import { useRoute } from 'vue-router'; |
||||
|
||||
export default { |
||||
name: "ArticleDetail", |
||||
components: { |
||||
BlogHeader, |
||||
BlogFooter, |
||||
}, |
||||
setup() { |
||||
let article = ref(null); |
||||
const route = useRoute(); // 用来解析路由动态参数:id |
||||
$.ajax({ |
||||
url: "http://127.0.0.1:6789/api/article/" + route.params.id, |
||||
type: 'GET', |
||||
success(resp){ |
||||
article.value=resp; |
||||
}, |
||||
error(resp) { |
||||
console.log(resp) |
||||
} |
||||
}); |
||||
|
||||
const formatted_time = (iso_date_string) => { |
||||
const date = new Date(iso_date_string); |
||||
return date.toLocaleDateString(); |
||||
} |
||||
|
||||
return { |
||||
article, |
||||
formatted_time, |
||||
} |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.grid-container { |
||||
display: grid; |
||||
grid-template-columns: 3fr 1fr; |
||||
} |
||||
|
||||
#title { |
||||
text-align: center; |
||||
font-size: x-large; |
||||
} |
||||
|
||||
#subtitle { |
||||
text-align: center; |
||||
color: gray; |
||||
font-size: small; |
||||
} |
||||
</style> |
||||
|
||||
<style> |
||||
.article-body p img { |
||||
max-width: 100%; |
||||
border-radius: 50px; |
||||
box-shadow: gray 0 0 20px; |
||||
|
||||
} |
||||
|
||||
.toc ul { |
||||
list-style-type: disc; |
||||
padding-inline-start: 15px; |
||||
} |
||||
|
||||
.toc a { |
||||
color: gray; |
||||
} |
||||
</style> |
@ -0,0 +1,22 @@ |
||||
<template> |
||||
<BlogHeader /> |
||||
<ArticleList /> |
||||
<BlogFooter /> |
||||
</template> |
||||
|
||||
<script> |
||||
import ArticleList from "@/components/ArticleList.vue"; |
||||
import BlogHeader from "@/components/BlogHeader.vue"; |
||||
import BlogFooter from "@/components/BlogFooter.vue"; |
||||
|
||||
export default { |
||||
name: "HomePage", |
||||
components: { |
||||
ArticleList, |
||||
BlogHeader, |
||||
BlogFooter, |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style></style> |
Loading…
Reference in new issue