文章模块基本完成

This commit is contained in:
2023-07-05 01:13:29 +08:00
parent 8f48b40482
commit 0946e22f85
17 changed files with 1127 additions and 376 deletions

980
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,10 +10,10 @@
"dependencies": {
"axios": "^1.4.0",
"core-js": "^3.8.3",
"element-tiptap": "^1.27.1",
"element-ui": "^2.15.13",
"vue": "^2.6.14",
"vue-cookie": "^1.1.4",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},

View File

@@ -15,7 +15,7 @@
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
background-color: white;
}
nav {

View File

@@ -302,6 +302,7 @@ export default {
});
},
}
}
</script>
@@ -336,4 +337,15 @@ export default {
/*overflow-y: hidden;*/
overflow-x: hidden;
}
.el-card{
border: none;
border-radius: 10px;
}
.el-tabs{
border: none;
border-radius: 10px;
}
.el-tabs__nav-scroll {
border-radius: 10px;
}
</style>

View File

@@ -206,7 +206,7 @@ export default {
_this.$emit('update:loginDialogVisible', false);
setTimeout(()=>{
window.location.reload();
},2000)
},1000)
} else {
Vue.prototype.$notify.error({

View File

@@ -36,6 +36,10 @@
<script>
export default {
name: "ProjectList",
data(){
return{
}
},
props: {
projectLists: Object
},
@@ -63,13 +67,13 @@ export default {
this.$router.push({
path:'/ProjectDetail',
query: {
id: this.projectLists.projectId,
id: this.projectLists.projectId, refresh: true
}})
// console.log(this.$route.query.id)
},
formatNumber(num) {
return num >= 1e3 && num < 1e4 ? (num / 1e3).toFixed(1) + 'k' : num >= 1e4 ? (num / 1e4).toFixed(1) + 'w' : num
}
},
}
}
</script>

View File

@@ -4,12 +4,12 @@
<span style="font-size: 14px;color: #4b5563">推荐项目</span>
<el-button class="randomProjectBtn" @click="getRandomProject" style="font-size: 12px;float: right; padding: 3px 0;color: #9ca3af" type="text"><i class="el-icon-refresh"></i>换一换</el-button>
</div>
<div class="text item" v-for="(item,index) in randomProjectList" :key="index" style="margin-top: 10px;display: flex;flex-direction: row;flex-wrap: nowrap">
<div class="text item" v-for="(item,index) in randomProjectList" :key="index" style=";cursor:pointer;margin-top: 10px;display: flex;flex-direction: row;flex-wrap: nowrap" @click="toProjectDetail(item.projectId)">
<div style="width: 40px;height: 40px;">
<el-avatar :size="40" :src="item.projectIco"></el-avatar>
</div>
<div style="display: flex;flex-direction: column;align-items: center;flex-wrap: nowrap;justify-content: left">
<span style="font-size: 14px;font-weight: bold;display: flex;flex-direction: row;justify-content: flex-start">{{item.projectName}}</span>
<div style="display: flex;flex-direction: column;flex-wrap: nowrap;justify-content: left">
<span style="margin-left: 10px;font-size: 14px;font-weight: bold;display: flex;flex-direction: row;justify-content: flex-start">{{item.projectName}}</span>
<div style=";margin-left:10px;margin-top: 5px;display: flex;flex-direction: row;justify-content: space-between;flex-wrap: nowrap">
<div style="align-items: center;font-size: 12px;color: #9ca3af">
<i class="el-icon-star-off"></i> <span>{{formatNumber(item.lookCount)}}</span>
@@ -54,7 +54,16 @@ export default {
},
formatNumber(num) {
return num >= 1e3 && num < 1e4 ? (num / 1e3).toFixed(1) + 'k' : num >= 1e4 ? (num / 1e4).toFixed(1) + 'w' : num
}
},
toProjectDetail(id){
this.$router.push({
path:'/ProjectDetail',
query: {
id: id,
refresh: true
}})
// console.log(this.$route.query.id)
},
}
}
</script>
@@ -63,4 +72,8 @@ export default {
.randomProjectBtn:hover{
color: #00ff0d;
}
.text:hover{
border-radius: 10px;
background-color: #eeeeee;
}
</style>

View File

@@ -29,6 +29,7 @@
<script>
import axios from "axios";
import Vue from "vue";
export default {
name: "UserInfo",
@@ -44,7 +45,18 @@ export default {
methods:{
signOut(){
this.$cookie.delete('username');
window.location.reload();
if(this.$cookie.get('username')===null){
Vue.prototype.$notify({
title: '成功',
message: ('i', {style: 'color: teal'}, "退出成功!"),
type: 'success',
offset: 50
});
}
setTimeout(()=>{
window.location.reload();
},1000)
},
toUserPage(){
this.$router.push({path:'/UserInfoPage'})

View File

@@ -1,46 +0,0 @@
<template>
<div style="display:flex;flex-direction:row;flex-wrap: nowrap">
<div style="display: flex;flex-direction:column;flex-wrap: nowrap">
<div class="PageHeader">
<br/>
<el-page-header @back="goBack" style="justify-content: center;">
<div slot="title" style="font-size:23px;font-weight: 600;"></div>
<div slot="content" style="font-size:23px;font-weight: 600;">
HelloGitHub 文章
</div>
</el-page-header>
</div>
<div class="PageContent">文章内容</div>
</div>
<!-- <div style="display: flex;flex-direction:column;flex-wrap: nowrap">-->
<!-- <div class="UserInfo">-->
<!-- 用户信息展示内容-->
<!-- </div>-->
<!-- <div class="RightContent">-->
<!-- 空位置待填入-->
<!-- </div>-->
<!-- <div class="ReferralProgram">-->
<!-- 推荐项目目录-->
<!-- </div>-->
<!-- </div>-->
</div>
</template>
<script>
export default {
name: "PaperComponent",
methods: {
goBack() {
window.history.go(-1);
},
}
}
</script>
<style scoped lang="scss">
::v-deep .el-page-header__left{
left:-250px;
}
</style>

View File

@@ -0,0 +1,107 @@
<template>
<div style="display:flex;flex-direction:row;flex-wrap: nowrap">
<div style="display: flex;flex-direction:column;flex-wrap: nowrap">
<div class="PageHeader">
<br/>
<el-page-header @back="goBack" style="justify-content: center;">
<div slot="title" style="font-size:23px;font-weight: 600;"></div>
<div slot="content" style="font-size:23px;font-weight: 600;">
{{ArticleTitle}}
</div>
</el-page-header>
</div>
<div class="PageContent" style="display: flex;flex-direction: column;flex-wrap: nowrap;align-items: center">
<el-image fit="cover" style="width: 50vw; height: 35vh" :src="articleico">
<div slot="placeholder" class="image-slot">
加载中<span class="dot">...</span>
</div>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<el-tiptap style="margin-top: 20px" v-model="ArticleContent" :readonly="true" :showMenubar="false" :extensions="extensions" />
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import {
Bold,
BulletList,
Doc,
Heading,
Italic,
ListItem,
OrderedList,
Paragraph,
Strike,
Text,
Underline
} from "element-tiptap";
export default {
name: "ArticleDetail",
data(){
return{
extensions: [
new Doc(),
new Text(),
new Paragraph(),
new Heading({ level: 5 }), // 支持多级标题设置为5级
new Bold({ bubble: false }), // 在气泡菜单中渲染菜单按钮
new Underline({ bubble: false, menubar: false }), // 在气泡菜单而不在菜单栏中渲染菜单按钮
new Italic(),
new Strike(),
new ListItem(),
new BulletList(),
new OrderedList(),
],
ArticleContent:null,
ArticleTitle:null,
articleico:'',
}
},
watch: {
$route () {
if(this.$route.query.refresh){
this.getArticleDetail() //重新调用http请求实现页面的重新渲染
}
}
},
mounted() {
this.getArticleDetail();
},
methods: {
goBack() {
window.history.go(-1);
},
getArticleDetail(){
var that=this;
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/selectByArticleId',
// URL 中的查询参数
params: {
articleid:this.$route.query.id
}
}).then(function (res) {
that.ArticleContent=res.data.ArticleContent;
that.ArticleTitle=res.data.ArticleTitle;
that.articleico=res.data.articleico;
});
},
}
}
</script>
<style scoped>
/*::v-deep .el-page-header__left{*/
/* left:-300px;*/
/*}*/
</style>

View File

@@ -0,0 +1,77 @@
<template>
<div class="articleList" @click="goArticleDetail">
<div style="display: flex;flex-direction: column;">
<div style="display: flex;justify-content: flex-start">
<span style="font-size: 16px;color: black;font-weight: bold">{{articleList.ArticleTitle}}</span>
</div>
<span v-text="brief" style="display: flex;justify-content:flex-start;text-align: left;margin-top: 10px;font-size: 13px;color: #9ca3af">
</span>
<div style="margin-top: 10px;display: flex;flex-direction: row;flex-wrap: wrap;align-items: center;font-size: 12px;color: #1f2937">
<span style="display: flex;justify-content: flex-start"> 作者: </span>
<span style="margin-left: 5px"> {{articleList.username}} </span>
<span style="margin-left: 5px"></span>
<span style="margin-left: 5px">发布于 </span>
<span style="margin-left: 5px">{{articleList.publishtime}}</span>
<span style="margin-left: 5px"></span>
<span style="margin-left: 5px">阅读: </span>
<span style="margin-left: 5px">{{ formatNumber(articleList.ReadCount) }}</span>
</div>
</div>
<div style="width: 100px;height: 100px;margin-right: 10px">
<el-avatar :size="100" shape="square" :src="articleList.articleico"></el-avatar>
</div>
</div>
</template>
<script>
export default {
name: "ArticleList",
props: {
articleList: Object
},
data(){
return {
}
},
computed:{
brief: function() {
return this.articleList.ArticleContent.substr(0, 100) + '...';
},
},
methods:{
formatNumber(num) {
return num >= 1e3 && num < 1e4 ? (num / 1e3).toFixed(1) + 'k' : num >= 1e4 ? (num / 1e4).toFixed(1) + 'w' : num
},
goArticleDetail(){
this.$router.push({
path:'/ArticleDetail',
query: {
id: this.articleList.ArticleId,
refresh: true
}})
// console.log(this.$route.query.id)
},
}
}
</script>
<style scoped>
.articleList{
height: 15vh;
width: 100%;
/*background-color: #59A3A4;*/
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
border-radius: 10px;
cursor: pointer;
overflow: hidden;
}
.articleList:hover{
background-color: #eeeeee;
}
</style>

View File

@@ -0,0 +1,145 @@
<template>
<div style="display:flex;flex-direction:row;flex-wrap: nowrap">
<div style="display: flex;flex-direction:column;flex-wrap: nowrap">
<div class="PageHeader">
<br/>
<el-page-header @back="goBack" style="justify-content: center;">
<div slot="title" style="font-size:23px;font-weight: 600;"></div>
<div slot="content" style="font-size:23px;font-weight: 600;display: flex;flex-direction: row;align-items: center;">
HelloGitHub 文章
</div>
</el-page-header>
</div>
<div class="PageContent">
<el-tabs type="border-card" style="border: none" v-model="avtiveName" @tab-click="getArticleList">
<el-tab-pane name="last">
<span slot="label"><i class="el-icon-star-on"></i> 最新</span>
<ul
class="list"
v-infinite-scroll="load"
infinite-scroll-disabled="disabled">
<ol v-for="(article,index) in articleList" :key="index" class="list-item"
style="display: flex;flex-direction: column;margin-left: -80px;" >
<ArticleList :article-list="article"></ArticleList>
<el-divider></el-divider>
</ol>
</ul>
<p v-if="loading" style="color: #9ca3af">加载中...</p>
<p v-if="noMore" style="color: #9ca3af">- 你不经意间触碰到了底线 -</p>
</el-tab-pane>
<el-tab-pane name="hot">
<span slot="label"><i class="el-icon-s-opportunity"></i> 最热</span>
<ul
class="list"
v-infinite-scroll="load"
infinite-scroll-disabled="disabled">
<ol v-for="(article,index) in articleList" :key="index" class="list-item"
style="display: flex;flex-direction: column;margin-left: -80px;" >
<ArticleList :article-list="article"></ArticleList>
<el-divider></el-divider>
</ol>
</ul>
<p v-if="loading" style="color: #9ca3af">加载中...</p>
<p v-if="noMore" style="color: #9ca3af">- 你不经意间触碰到了底线 -</p>
</el-tab-pane>
</el-tabs>
</div>
</div>
<div style="display: flex;margin-left: 20px;margin-top: 7vh;flex-direction: column">
<el-card class="box-card" style="width: 15vw;height: auto;border: none">
<el-button type="info" plain @click="openLogin" v-show="this.$cookie.get('username')==null"> </el-button>
<LoginDialog :login-dialog-visible.sync="loginDialogVisible"></LoginDialog>
<UserInfo></UserInfo>
</el-card>
<RandomProjects style="margin-top: 20px"></RandomProjects>
</div>
</div>
</template>
<script>
import axios from "axios";
import ArticleList from "@/components/Paper/ArticleList.vue";
import UserInfo from "@/components/Home/UserInfo.vue";
import LoginDialog from "@/components/Home/LoginDialog.vue";
import RandomProjects from "@/components/Home/RandomProjects.vue";
export default {
name: "PaperComponent",
components: {RandomProjects, LoginDialog, UserInfo, ArticleList},
data(){
return{
avtiveName:'last',
articleList:null,
count: 10,
loading: false,
loginDialogVisible:false,
}
},
mounted() {
this.getArticleListBylast();
},
computed: {
noMore() {
return this.count >= 10
},
disabled() {
return this.loading || this.noMore
}
},
methods: {
openLogin(){
this.loginDialogVisible=true;
},
goBack() {
window.history.go(-1);
},
load() {
this.loading = true
setTimeout(() => {
this.count += 2
this.loading = false
}, 2000)
},
getArticleList(tab,event){
var that=this;
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/articleSort',
// URL 中的查询参数
params: {
sort_by:tab.name
}
}).then(function (res) {
that.articleList=res.data;
});
},
getArticleListBylast(){
var that=this;
axios({
method: 'post',
// 请求的地址
url: 'http://localhost:8082/helloGithub_war_exploded/articleSort',
// URL 中的查询参数
params: {
sort_by:"last"
}
}).then(function (res) {
// console.log(res)
that.articleList=res.data;
});
},
}
}
</script>
<style scoped lang="scss">
::v-deep .el-page-header__left{
left:-250px;
}
</style>

View File

@@ -113,7 +113,7 @@
<div>
<el-tabs v-model="activeName">
<el-tab-pane label="介绍" name="first">
<quill-editor :editorOption="editorOption" :value="projectDescription" :disabled="true"></quill-editor>
<el-tiptap v-model="projectDescription" :readonly="true" :showMenubar="false" :extensions="extensions" />
<div style="display:flex;align-items: center;flex-direction: row;">
<span style="font-size: 14px;margin-top: 10px">收录于: </span><el-tag style="margin-left: 10px;margin-top: 10px" size="medium"> {{periodicals}} </el-tag>
<div style="display: flex;flex-direction: row;margin-left: 10px;margin-top: 10px;align-items: center">
@@ -126,7 +126,7 @@
</el-tab-pane>
<el-tab-pane label="代码" name="second">
<quill-editor :editorOption="editorOption" :disabled="true"></quill-editor>
<el-tiptap :readonly="true" :showMenubar="false" :extensions="extensions" />
</el-tab-pane>
</el-tabs>
</div>
@@ -232,6 +232,20 @@ import UserInfo from "@/components/Home/UserInfo.vue";
import LoginDialog from "@/components/Home/LoginDialog.vue";
import Vue from "vue";
import RandomProjects from "@/components/Home/RandomProjects.vue";
import {
// 罗列出需要的功能按钮
Doc,
Text,
Paragraph,
Heading,
Bold,
Underline,
Italic,
Strike,
ListItem,
BulletList,
OrderedList,
} from 'element-tiptap';
export default {
name: "ProjectDetail",
@@ -263,6 +277,19 @@ export default {
projectId:null,
commentContent:[],
commentNum:0,
extensions: [
new Doc(),
new Text(),
new Paragraph(),
new Heading({ level: 5 }), // 支持多级标题设置为5级
new Bold({ bubble: true }), // 在气泡菜单中渲染菜单按钮
new Underline({ bubble: true, menubar: false }), // 在气泡菜单而不在菜单栏中渲染菜单按钮
new Italic(),
new Strike(),
new ListItem(),
new BulletList(),
new OrderedList(),
],
}
},
mounted() {
@@ -270,6 +297,13 @@ export default {
this.getComment();
},
watch: {
$route () {
if(this.$route.query.refresh){
this.getProjectDetail() //重新调用http请求实现页面的重新渲染
}
}
},
methods:{
goBack() {
window.history.go(-1);
@@ -302,6 +336,7 @@ export default {
openLogin(){
this.loginDialogVisible=true;
},
getComment(){
var that=this;
axios({

View File

@@ -12,18 +12,18 @@
</div>
<div class="PageContent">
<el-card class="box-card" style="border: none">
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;align-items: center;justify-content: flex-start">
<div style="display: flex;flex-direction: row;align-items: center;justify-content: flex-start">
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;justify-content: flex-start">
<div style="display: flex;flex-direction: row;justify-content: flex-start">
<div style="width: 100px;height: 100px">
<el-avatar :size="90">{{this.$cookie.get('username')}}</el-avatar>
</div>
<div style="display: flex;flex-direction: column;align-items: center;margin-left: 15px;">
<div style="display: flex;flex-direction: row;align-items: center;justify-content: flex-start;margin-left: -27vw">
<div style="display: flex;flex-direction: column;margin-left: 15px;">
<div style="display: flex;flex-direction: row;align-items: center;justify-content: flex-start;">
<span style="font-size: 20px;font-weight: bold;">{{this.$cookie.get('username')}}</span>
<span style="font-size: 15px;font-weight: bold;color: #3b82f6;margin-left: 10px">Lv.1</span>
</div>
<span style="margin-top: 10px;color: #6b7280;font-size: 15px">你是 HelloGitHub 社区的第<span style="font-size: 16px;color:#2b2e33;font-weight: bold "> 7750 </span>位用户 2023 06 25 加入</span>
<span style="margin-right: 8vw;margin-top: 10px;color: #6b7280;font-size: 15px">已分享<span style="font-size: 16px;color:#2b2e33;font-weight: bold ">0</span>个开源项目<span style="font-size: 16px;color:#2b2e33;font-weight: bold ">0</span>份项目评价共获得<span style="font-size: 16px;color:#2b2e33;font-weight: bold ">0</span>点贡献值</span>
<span style="display: flex;justify-content: flex-start;margin-top: 10px;color: #6b7280;font-size: 15px">已分享<span style="font-size: 16px;color:#2b2e33;font-weight: bold ">0</span>个开源项目<span style="font-size: 16px;color:#2b2e33;font-weight: bold ">0</span>份项目评价共获得<span style="font-size: 16px;color:#2b2e33;font-weight: bold ">0</span>点贡献值</span>
</div>
</div>
</div>
@@ -33,9 +33,6 @@
<el-tab-pane label="评论" name="first">
<el-empty description="暂无评论" :image-size="100"></el-empty>
</el-tab-pane>
<el-tab-pane label="点赞" name="second">
<el-empty description="暂无点赞" :image-size="100"></el-empty>
</el-tab-pane>
<el-tab-pane label="项目" name="third">
<el-empty description="暂无项目" :image-size="100"></el-empty>
</el-tab-pane>
@@ -66,6 +63,7 @@ export default {
<style scoped>
::v-deep .el-page-header__left{
left:-300px;
position: relative;
left:-20vw;
}
</style>

View File

@@ -6,13 +6,16 @@ import './assets/styles/element-variables.scss'
import axios from "axios";
import './assets/icon/iconfont.css'
import store from './store'
// 引入富文本组件
import QuillEditor from 'vue-quill-editor'
// 引入富文本组件样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(QuillEditor)
import { ElementTiptapPlugin } from 'element-tiptap';
// 引入 ElementUI 样式
// import 'element-ui/lib/theme-chalk/index.css';
// import element-tiptap 样式
import 'element-tiptap/lib/index.css';
Vue.use(ElementTiptapPlugin, {
/* 插件配置项 */
lang: 'zh',
});
axios.defaults.withCredentials=true;

View File

@@ -4,11 +4,15 @@ import index from '../views/index.vue'
import home from "@/components/Home/Home.vue";
import monthly from "@/components/Monthly/Monthly.vue";
import ranking from "@/components/Ranking.vue";
import paper from "@/components/Paper.vue";
import paper from "@/components/Paper/Paper.vue";
import MonthlyDetail from "@/components/Monthly/MonthlyDetail.vue";
import UserInfoPage from "@/components/UserInfoPage.vue";
import ProjectDetail from "@/components/ProjectDetail.vue";
import ArticleDetail from "@/components/Paper/ArticleDetail.vue";
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
Vue.use(VueRouter)
const routes = [
@@ -57,6 +61,11 @@ const routes = [
name: 'ProjectDetail',
component: ProjectDetail
},
{
path: '/ArticleDetail',
name: 'ArticleDetail',
component: ArticleDetail
},
]
}

View File

@@ -5,9 +5,7 @@
</el-header>
<el-container>
<el-main>
<keep-alive>
<router-view></router-view>
</keep-alive>
</el-main>
</el-container>
</el-container>