mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-10 11:26:43 +08:00
683 lines
20 KiB
Vue
683 lines
20 KiB
Vue
2<template>
|
||
<div id="article-list-content" class="article-list-content">
|
||
<div class="article-banner">
|
||
<portal-header current="article" textColor="#ffffff" @emitInput="emitInput"></portal-header>
|
||
</div>
|
||
<!--内容区域-->
|
||
<div style="padding-top:30px" class="">
|
||
<div class="xcontent2">
|
||
<div class="xcontent2-main" style="margin-right: 30px;background-color: #fff;padding-top: 50px;">
|
||
<div>
|
||
<div style="padding:0px" class="left-div">
|
||
<div class="order-div">
|
||
<div class="quyer-tag">
|
||
<el-button type="text" class="order-class" @click="getData(2)" :class="{ actice: articleList.order == 2 }"> 最热 </el-button>
|
||
<el-button type="text" class="order-class" @click="getData(1)" :class="{ actice: articleList.order == 1 }"> 最新 </el-button>
|
||
</div>
|
||
<span class="more"></span>
|
||
</div>
|
||
<div class="data-content" v-if="articleList.list.length > 0">
|
||
<div v-for="(article, aidx) in articleList.list" :key="aidx" class="article-list">
|
||
<div class="article-info">
|
||
<!--title-->
|
||
<router-link :to="'article/detail?id=' + article.id">
|
||
<div style="display: flex;justify-content: space-between;margin-bottom: 10px;">
|
||
<div class="article-title one-line-ellipsis" v-html="$keywordActiveShow(article.title,articleList.keyword)"></div>
|
||
<div class="article-info-date"><i style="font-size:14px" class="el-icon-time"></i> {{article.sysCreateTime}}</div>
|
||
</div>
|
||
</router-link>
|
||
<!--body-->
|
||
<div class="article-body" style="display: flex;justify-content: space-between;">
|
||
|
||
<div style="flex: 1;">
|
||
<router-link :to="'article/detail?id=' + article.id">
|
||
<div style="padding-top: 5px;">
|
||
<div class="article-info-summary" :style="{height:article.coverurl==''? '50px':'100px'}" :class="article.coverurl==''? 'two-line-ellipsis':'four-line-ellipsis'">{{ article.summary }}</div>
|
||
</div>
|
||
</router-link>
|
||
</div>
|
||
<router-link :to="'article/detail?id=' + article.id">
|
||
<div class="article-image" v-if="article.coverurl">
|
||
<article-image :article="article"></article-image>
|
||
</div>
|
||
</router-link>
|
||
</div>
|
||
<!--互动内容-->
|
||
<div style="display: flex;justify-content:flex-start;align-items: center;margin-top: 0px;">
|
||
<div style="flex:1;">
|
||
<author :avatar="article.authorInfo.avatar" :name="article.sysCreateBy" :sex="article.authorInfo.sex" :aid="article.authorInfo.aid"></author>
|
||
</div>
|
||
<div style="">
|
||
<interactBar nodeWidth="60px" :readonly="true" :type="2" :data="article" :views="false"></interactBar>
|
||
</div>
|
||
<!-- <author :avatar="article.authorInfo.avatar" :name="article.sysCreateBy" :info="article.authorInfo.orgInfo"></author> -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- <div class="pagination-div" v-if="isMore"><span class="pag-text" @click="loadMore()">加载更多</span></div> -->
|
||
<div class="pagination-div">
|
||
<span class="pag-text" @click="loadMore()" v-if="moreState == 1">加载更多</span>
|
||
<span class="pag-text-msg" v-else-if="moreState == 2">数据加载中</span>
|
||
<span class="pag-text-msg" v-else-if="moreState == 3 && !isSeach">没有更多数据了</span>
|
||
<span class="pag-text-msg" v-else-if="isSeach">没有查询到相关内容</span>
|
||
</div>
|
||
<div v-if="isSeach" style="height:382px"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="xcontent2-minor">
|
||
<div>
|
||
<div id="articleAnking">
|
||
<div>
|
||
<div class="portal-model-btn pointer" @click="openDialog">
|
||
<svg-icon style="margin-right: 10px;font-size: 24px;" icon-class="addArticle"></svg-icon>
|
||
写文章
|
||
</div>
|
||
</div>
|
||
<div class="portal-ranking ranking-bg">
|
||
<p class="ranking-title">贡献榜</p>
|
||
<ul class="ranking-data">
|
||
<li v-for="(item, index) in ankingList" :key="index" style="margin-top:30px;line-height: 22px;cursor: pointer;">
|
||
<span class="portal-right-text orange-one" v-if="index==0" style="margin-right:94px">
|
||
<img src="/images/list-01.png" alt="">
|
||
</span>
|
||
<span class="portal-right-text orange-tow" v-if="index==1" style="margin-right:94px">
|
||
<img src="/images/list02.png" alt="">
|
||
</span>
|
||
<span class="portal-right-text orange-three" v-if="index==2" style="margin-right:94px">
|
||
<img src="/images/list03.png" alt="">
|
||
</span>
|
||
<span class="portal-right-text" v-if="index==3" style="margin-right:94px">
|
||
<img src="/images/list04.png" alt="">
|
||
</span>
|
||
<span class="portal-right-text" v-if="index==4" style="margin-right:94px">
|
||
<img src="/images/list05.png" alt="">
|
||
</span>
|
||
<span class="portal-title-desc">{{ item.sysCreateUname }}</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="course-resources">
|
||
<!-- 资源位 -->
|
||
<img :src="fileBaseUrl + resonimg.image" alt="">
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
<el-dialog title="创建文章" :visible.sync="diagSync" :close-on-click-modal="false" width="900px" custom-class="g-dialog">
|
||
<editItems v-if="diagSync" :jumpLimit="false" :editForm="{}" @success="saveSuccess"></editItems>
|
||
</el-dialog>
|
||
<portal-footer></portal-footer>
|
||
<portalFloatTools></portalFloatTools>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapGetters } from 'vuex';
|
||
import portalHeader from '@/components/PortalHeader.vue';
|
||
import portalFooter from '@/components/PortalFooter.vue';
|
||
import portalFloatTools from '@/components/PortalFloatTools.vue';
|
||
import interactBar from '@/components/Portal/interactBar.vue';
|
||
import timeShow from '@/components/Portal/daytimeShow.vue';
|
||
import author from '@/components/Portal/authorInfo.vue';
|
||
import apiArticle from '@/api/modules/article.js';
|
||
import apiUser from '@/api/system/user.js';
|
||
import apiSearchterm from '@/api/modules/searchterm.js';
|
||
import articleImage from '@/components/Article/articleImage.vue';
|
||
import editItems from '@/components/Article/editItems.vue';
|
||
import apiPlace from "@/api/phase2/place.js"
|
||
export default {
|
||
name: 'index',
|
||
components: { editItems,portalHeader, portalFooter,articleImage, portalFloatTools, interactBar, timeShow, author },
|
||
computed: {
|
||
...mapGetters(['userInfo']),
|
||
// isMore() {
|
||
// let isOk = true;
|
||
// if (this.articleList.list.length === this.count) {
|
||
// isOk = false;
|
||
// }
|
||
// return isOk;
|
||
// }
|
||
},
|
||
data() {
|
||
return {
|
||
resonimg:{},
|
||
moreState:1,// 1 加载更多 2 加载中 3无数据
|
||
searchRecords: [],
|
||
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
|
||
articleList: {
|
||
pageIndex: 1,
|
||
pageSize: 10,
|
||
order: 2,
|
||
keyword:'',
|
||
list: []
|
||
},
|
||
count: 0,
|
||
order: 1,
|
||
articleForm: {
|
||
title: '',
|
||
content: ''
|
||
},
|
||
keyword: '',
|
||
searchTags: [],
|
||
ankingList: [],
|
||
ankingWidth:'100%',
|
||
ankingFixed:false,
|
||
diagSync:false,//控制弹窗
|
||
// articleList: []
|
||
isSeach:false,
|
||
};
|
||
},
|
||
mounted() {
|
||
// let el_anking = document.querySelector('#articleAnking');
|
||
// this.ankingWidth=el_anking.clientWidth;
|
||
//console.log(el_anking.clientWidth,'clientWidth');
|
||
if(this.$route.query){
|
||
this.articleList.keyword = this.$route.query.keyword;
|
||
}
|
||
|
||
if(this.articleList.keyword != '') {
|
||
this.isSeach = true;
|
||
}
|
||
this.getArticleList();
|
||
this.getAnkingData();
|
||
this.searchterm();
|
||
let height = 200;
|
||
let $this = this;
|
||
window.addEventListener(
|
||
"scroll",
|
||
this.handleScroll
|
||
);
|
||
this.couresreso();
|
||
},
|
||
beforeDestroy(){
|
||
window.removeEventListener("scroll",this.handleScroll);
|
||
},
|
||
methods: {
|
||
couresreso(){
|
||
let key = 'article';
|
||
apiPlace.detail(key).then(res=>{
|
||
console.log(res)
|
||
let lmj = JSON.parse(res.result.content)
|
||
// console.log(lmj)
|
||
this.resonimg = lmj[0]
|
||
console.log(this.resonimg.image)
|
||
})
|
||
},
|
||
emitInput(val){
|
||
this.articleList.keyword = val;
|
||
this.isSeach =true;
|
||
this.searchData();
|
||
},
|
||
saveSuccess(data){
|
||
this.diagSync=false;
|
||
this.articleList.pageIndex = 1;
|
||
this.articleList.list = [];
|
||
this.getArticleList();
|
||
},
|
||
openDialog(){
|
||
this.diagSync=true
|
||
},
|
||
handleScroll() {
|
||
let el_anking = document.querySelector('#articleAnking');
|
||
//console.log(el_anking.clientWidth,'clientWidth');
|
||
//el_anking.wid
|
||
let innerHeight = document.querySelector('#article-list-content').clientHeight
|
||
let outerHeight = document.documentElement.clientHeight
|
||
let outerWidth = el_anking.clientWidth;
|
||
let scrollTop = document.documentElement.scrollTop
|
||
if ((outerHeight + scrollTop + 350) >= innerHeight) {
|
||
if(this.moreState == 1) {
|
||
this.debounce(this.loadMore(),5000);
|
||
}
|
||
}
|
||
// console.log(scrollTop,'scrollTop');
|
||
// console.log(innerHeight,'innerHeight');
|
||
// console.log(outerHeight,'outerHeight');
|
||
// if(scrollTop>90){
|
||
// if(this.ankingFixed){
|
||
// this.ankingFixed=false;
|
||
// el_anking.classList.add('anking-fixed');
|
||
// }
|
||
|
||
// }else{
|
||
// if(!this.ankingFixed){
|
||
// this.ankingFixed=true;
|
||
// el_anking.classList.remove('anking-fixed');
|
||
// }
|
||
// }
|
||
if(scrollTop > 400) {
|
||
document.querySelector('#articleAnking').style.cssText = "position: fixed;top: 0;width:"+outerWidth+"px";
|
||
} else {
|
||
document.querySelector('#articleAnking').style.cssText = "position: static";
|
||
}
|
||
},
|
||
debounce(func, wait) {// 非立即执行
|
||
let timeout;
|
||
return function () {
|
||
let context = this;
|
||
let args = arguments;
|
||
if (timeout) clearTimeout(timeout);
|
||
timeout = setTimeout(() => {
|
||
func.apply(context, args)
|
||
}, wait);
|
||
}
|
||
},
|
||
// debounce(func,wait) {//立即执行
|
||
// let timeout;
|
||
// return function () {
|
||
// let context = this;
|
||
// let args = arguments;
|
||
// if (timeout) clearTimeout(timeout);
|
||
// let callNow = !timeout;
|
||
// timeout = setTimeout(() => {
|
||
// timeout = null;
|
||
// }, wait)
|
||
|
||
// if (callNow) func.apply(context, args)
|
||
// }
|
||
// },
|
||
searchData(){
|
||
apiSearchterm.save({ keyword: this.articleList.keyword, type: 2 });
|
||
this.articleList.pageIndex = 1;
|
||
this.articleList.list = [];
|
||
this.getArticleList();
|
||
},
|
||
getData(num) {
|
||
this.articleList.order = num;
|
||
this.articleList.pageIndex = 1;
|
||
this.articleList.list = [];
|
||
this.getArticleList();
|
||
},
|
||
useHotword(item) {
|
||
this.articleList.keyword = item.keyword;
|
||
this.articleList.pageIndex = 1;
|
||
this.articleList.list = [];
|
||
this.getArticleList();
|
||
},
|
||
searchterm() {
|
||
apiSearchterm.list(5, 2).then(res => {
|
||
if (res.status === 200) {
|
||
this.searchRecords = res.result;
|
||
}
|
||
});
|
||
},
|
||
loadMore() {
|
||
this.articleList.pageIndex += 1;
|
||
this.getArticleList();
|
||
},
|
||
handleSizeChange(item) {
|
||
this.articleList.pageSize = item;
|
||
},
|
||
handleCurrentChange(item) {
|
||
this.articleList.pageIndex = item;
|
||
},
|
||
getArticleList() {
|
||
this.moreState = 2;
|
||
let { pageIndex, pageSize, order, keyword } = this.articleList;
|
||
const query = { pageIndex, pageSize, order, keyword };
|
||
let that = this;
|
||
// portalPageList接口换了,这是原来的
|
||
apiArticle.findPortal(query).then(res => {
|
||
if (res.status == 200 && res.result.list.length > 0) {
|
||
this.isSeach =false;
|
||
let ids = [];
|
||
res.result.list.forEach(item => {
|
||
item.authorInfo = {aid:'', name: '', avatar: '', orgInfo: '' ,sex:null};
|
||
ids.push(item.sysCreateAid);
|
||
});
|
||
that.getQaUserData(res.result.list, ids);
|
||
this.count = res.result.count;
|
||
that.articleList.list.push(...res.result.list);
|
||
that.moreState = 1;
|
||
if(res.result.count === res.result.list.length) {
|
||
this.moreState = 3;
|
||
}
|
||
} else {
|
||
this.moreState = 3;
|
||
// this.$message.error(res.message);
|
||
}
|
||
});
|
||
},
|
||
getQaUserData(list, ids) {
|
||
const noReapetIds = [...new Set(ids)];
|
||
apiUser.getByIds(noReapetIds).then(res => {
|
||
if (res.status == 200) {
|
||
list.forEach(item => {
|
||
res.result.some(author => {
|
||
if (author.aid == item.sysCreateAid) {
|
||
item.authorInfo.aid = author.aid;
|
||
item.authorInfo.avatar = author.avatar;
|
||
item.authorInfo.name = author.name;
|
||
item.authorInfo.orgInfo = author.orgInfo;
|
||
item.authorInfo.sex = author.sex;
|
||
}
|
||
});
|
||
});
|
||
} else {
|
||
// this.$message({ message: res.message, type: 'error' });
|
||
}
|
||
});
|
||
},
|
||
goTarget(href) {
|
||
window.open(this.webBaseUrl+href, '_blank');
|
||
},
|
||
showInApply() {
|
||
this.inapply.show = true;
|
||
},
|
||
findOrg() {
|
||
//
|
||
},
|
||
publishArticle() {
|
||
this.$router.push('/article/add');
|
||
},
|
||
submitCreate() {
|
||
this.$refs['applyForm'].validate(valid => {
|
||
if (valid) {
|
||
}
|
||
});
|
||
},
|
||
getAnkingData() {
|
||
apiArticle.countsUsername(5).then(res => {
|
||
if (res.status == 200) {
|
||
this.ankingList = res.result;
|
||
}
|
||
});
|
||
},
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.course-resources{
|
||
margin-top: 26px;
|
||
width:100%;
|
||
img{
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 8px;
|
||
}
|
||
}
|
||
.article-banner{
|
||
height: 240px;
|
||
background: url('/images/article-banner.png');
|
||
}
|
||
.write-art{
|
||
width: 410px;
|
||
height: 67px;
|
||
text-align: center;
|
||
background: #DDEDFF;
|
||
border-radius: 8px;
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
border: none;
|
||
color: #387DF7;
|
||
margin-bottom: 22px;
|
||
}
|
||
::v-deep .el-card__body{
|
||
padding: 0;
|
||
}
|
||
::v-deep .bacolor:nth-child(odd){
|
||
background-color: #fff;
|
||
padding: 0 5px;
|
||
}
|
||
::v-deep .bacolor:nth-child(even){
|
||
background-color: #f6f6f6;
|
||
padding: 0 5px;
|
||
}
|
||
.anking-fixed {
|
||
position: fixed;
|
||
top: 0px;
|
||
background-color: #f0f0f0;
|
||
z-index: 999;
|
||
}
|
||
.left{
|
||
text-align: left;
|
||
}
|
||
.right{
|
||
text-align: right;
|
||
}
|
||
.one-line-ellipsis{
|
||
display: -webkit-box;
|
||
white-space:pre-wrap;
|
||
overflow: hidden;
|
||
text-overflow:ellipsis;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 1;
|
||
box-sizing: border-box;
|
||
// width: 80%;
|
||
}
|
||
.two-line-ellipsis{
|
||
display: -webkit-box;
|
||
// white-space:pre-wrap;
|
||
overflow: hidden;
|
||
line-height: 30px;
|
||
text-overflow:ellipsis;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 2;
|
||
box-sizing: border-box;
|
||
}
|
||
.four-line-ellipsis{
|
||
display: -webkit-box;
|
||
// white-space:pre-wrap;
|
||
overflow: hidden;
|
||
line-height: 25px;
|
||
text-overflow:ellipsis;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 4;
|
||
box-sizing: border-box;
|
||
}
|
||
.left-div {
|
||
border: none;
|
||
.search-div{
|
||
padding: 20px;
|
||
// padding-top: 20px;
|
||
::v-deep .el-input{
|
||
width: 420px;
|
||
height: 38px;
|
||
margin-bottom: 13px;
|
||
.el-input__inner{
|
||
height: 38px;
|
||
border-radius: 0;
|
||
}
|
||
.el-input-group__append{
|
||
width: 44px;
|
||
height: 38px;
|
||
border: 0;
|
||
padding: 0;
|
||
background:#3E7FFF;
|
||
border-radius: 0;
|
||
.el-button{
|
||
margin: 0;
|
||
border: 0;
|
||
width: 100%;
|
||
height: 38px;
|
||
padding: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
.el-icon-search{
|
||
color: #fff;
|
||
font-size: 22px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.tip{
|
||
color:#999999;
|
||
font-size: 12px;
|
||
span{
|
||
margin-right: 8px;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
}
|
||
.quyer-tag {
|
||
::v-deep .el-button{
|
||
width: 44px;
|
||
height: 26px;
|
||
padding: 0;
|
||
}
|
||
.order-class {
|
||
color: #6E7B84;
|
||
background-color: #FFFFFF;
|
||
border-radius: 4px;
|
||
height: 32px;
|
||
line-height: 32px;
|
||
font-size: 14px;
|
||
.el-icon--right {
|
||
margin-left: 0;
|
||
}
|
||
}
|
||
.actice {
|
||
border: 0px;
|
||
background: #387DF7;
|
||
color: #fff;
|
||
}
|
||
}
|
||
/* 分页div */
|
||
.pagination-div {
|
||
text-align: center;
|
||
padding: 10px 0;
|
||
}
|
||
.order-div {
|
||
padding: 0 20px;
|
||
background-color: #fff;
|
||
margin-bottom: 20px;
|
||
}
|
||
.data-content {
|
||
background-color: #fff;
|
||
padding: 5px 9px;
|
||
min-height: 364px;
|
||
.article-list:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.article-list:first-child {
|
||
margin-top: -24px;
|
||
}
|
||
.article-list {
|
||
padding: 24px 10px;
|
||
border-bottom: 1px solid #E8E8E8;
|
||
}
|
||
.search-div {
|
||
background: #fff;
|
||
padding: 10px 25px 0 25px;
|
||
.input-with-select {
|
||
.tip {
|
||
line-height: 35px;
|
||
font-size: 12px;
|
||
color: #999;
|
||
margin-bottom: 10px;
|
||
}
|
||
}
|
||
.tip {
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.ranking-title {
|
||
// padding-top: 20px;
|
||
line-height: 34px;
|
||
.center-titlt{
|
||
font-size: 15px;
|
||
color: #333333;
|
||
}
|
||
.center{
|
||
text-align: right;
|
||
}
|
||
img{
|
||
margin-top: 5px;
|
||
}
|
||
}
|
||
|
||
.right-box {
|
||
.add-btn {
|
||
width: 100%;
|
||
padding: 15px 0;
|
||
}
|
||
|
||
.ranking-data {
|
||
margin: 10px 0;
|
||
color: #999999;
|
||
}
|
||
}
|
||
|
||
.article-info {
|
||
// display: flex;
|
||
.article-title {
|
||
// height: 30px;
|
||
// line-height: 30px;
|
||
font-family: PingFang SC-Medium, PingFang SC;
|
||
font-size: 18px;
|
||
line-height: 30px;
|
||
color: #121212;
|
||
font-weight: 600;
|
||
flex:1;
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 1;
|
||
overflow: hidden;
|
||
word-break:break-all;
|
||
|
||
}
|
||
.article-info-date {
|
||
font-size: 12px;
|
||
line-height: 30px;
|
||
color: #999999;
|
||
i {
|
||
margin-right: 3px;
|
||
}
|
||
}
|
||
.art-box{
|
||
position: relative;
|
||
p{
|
||
position: absolute;
|
||
float: left;
|
||
top: 20px;
|
||
left: 10px;
|
||
color: #ffffff;
|
||
font-size: 14px;
|
||
line-height: 30px;
|
||
padding-right: 10px;
|
||
}
|
||
}
|
||
.article-image {
|
||
width: 156px;
|
||
height: 105px;
|
||
margin-left: 18px;
|
||
::v-deep .el-image{
|
||
border-radius: 4px;
|
||
}
|
||
}
|
||
.article-body {
|
||
// margin: 10px 0px;
|
||
margin-bottom: 20px;
|
||
.article-info {
|
||
font-size: 16px;
|
||
}
|
||
.article-info-summary {
|
||
word-break: break-all;
|
||
height: 100px;
|
||
line-height: 25px;
|
||
color: #333333;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
}
|
||
}
|
||
}
|
||
::v-deep .item-author{
|
||
margin-right: 100px;
|
||
margin-top: -7px;
|
||
// margin-top: 5px;
|
||
}
|
||
</style>
|