10 changed files with 1108 additions and 1 deletions
@ -0,0 +1,45 @@ |
|||
import request from '@/utils/request'; |
|||
import { AxiosPromise } from 'axios'; |
|||
import { UserDetail, UserQuery, NaviQuery, Navi ,PageParam,graphicformList} from './types'; |
|||
|
|||
|
|||
//获取当前用户详细信息
|
|||
export function getUserDetail(data: UserQuery): AxiosPromise<UserDetail> { |
|||
return request({ |
|||
url: '/javasys/user/detail', |
|||
method: 'post', |
|||
data: data, |
|||
|
|||
}); |
|||
} |
|||
|
|||
//获取左侧导航栏信息
|
|||
export function getZxxyNavis(data: NaviQuery): AxiosPromise<Navi[]> { |
|||
return request({ |
|||
url: '/javasys/archive/zxxy', |
|||
method: 'post', |
|||
data: data, |
|||
|
|||
}); |
|||
} |
|||
|
|||
//获取推荐分页
|
|||
export function getTuijian(data: PageParam): AxiosPromise<graphicformList> { |
|||
return request({ |
|||
url: '/javasys/graphicform/cardlist', |
|||
method: 'post', |
|||
data: data, |
|||
|
|||
}); |
|||
|
|||
} |
|||
//获取轮播图数据
|
|||
export function getCarousel(data: PageParam): AxiosPromise<graphicformList> { |
|||
return request({ |
|||
url: '/javasys/graphicform/carousel', |
|||
method: 'post', |
|||
data: data, |
|||
|
|||
}); |
|||
|
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
|
|||
|
|||
// 滚动监听器
|
|||
export function onScroll() { |
|||
|
|||
|
|||
// 获取所有锚点元素
|
|||
const navContents = document.querySelectorAll('.models') |
|||
|
|||
// 所有锚点元素的 offsetTop
|
|||
const offsetTopArr = [] |
|||
navContents.forEach(item => { |
|||
offsetTopArr.push(item.offsetTop) |
|||
}) |
|||
// 获取当前文档流的 scrollTop
|
|||
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop |
|||
// 定义当前点亮的导航下标
|
|||
let navIndex = 0 |
|||
for (let n = 0; n < offsetTopArr.length; n++) { |
|||
// 如果 scrollTop 大于等于第n个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
|
|||
// 那么此时导航索引就应该是n了
|
|||
if (scrollTop+210 >= offsetTopArr[n]) { |
|||
navIndex = n |
|||
} |
|||
//若滚动条已经到底则直接激活最后一个导航
|
|||
if (scrollTop + document.documentElement.clientHeight === document.documentElement.scrollHeight) { |
|||
navIndex = offsetTopArr.length - 1; |
|||
} |
|||
} |
|||
//active.value = navIndex
|
|||
return navIndex; |
|||
} |
|||
|
|||
// 跳转到指定索引的元素
|
|||
export function scrollTo(index) { |
|||
|
|||
|
|||
// 获取目标的 offsetTop
|
|||
// css选择器是从 1 开始计数,我们是从 0 开始,所以要 +1
|
|||
const targetOffsetTop = document.querySelector(`.content .models:nth-child(${index + 1})`).offsetTop |
|||
// 获取当前 offsetTop
|
|||
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop |
|||
// 定义一次跳 150 个像素
|
|||
const STEP = 50 |
|||
// 判断是往下滑还是往上滑
|
|||
if (scrollTop > targetOffsetTop) { |
|||
// 往上滑
|
|||
smoothUp() |
|||
} else { |
|||
// 往下滑
|
|||
smoothDown() |
|||
} |
|||
// 定义往下滑函数
|
|||
function smoothDown() { |
|||
// 如果当前 scrollTop 小于 targetOffsetTop 说明视口还没滑到指定位置
|
|||
if (scrollTop < targetOffsetTop) { |
|||
// 如果和目标相差距离大于等于 STEP 就跳 STEP
|
|||
// 否则直接跳到目标点,目标是为了防止跳过了。
|
|||
if (targetOffsetTop - scrollTop >= STEP) { |
|||
scrollTop += STEP |
|||
} else { |
|||
scrollTop = targetOffsetTop |
|||
} |
|||
document.body.scrollTop = scrollTop |
|||
document.documentElement.scrollTop = scrollTop |
|||
// 关于 requestAnimationFrame 可以自己查一下,在这种场景下,相比 setInterval 性价比更高
|
|||
requestAnimationFrame(smoothDown) |
|||
} |
|||
} |
|||
// 定义往上滑函数
|
|||
function smoothUp() { |
|||
if (scrollTop > targetOffsetTop) { |
|||
if (scrollTop - targetOffsetTop >= STEP) { |
|||
scrollTop -= STEP |
|||
} else { |
|||
scrollTop = targetOffsetTop |
|||
} |
|||
document.body.scrollTop = scrollTop |
|||
document.documentElement.scrollTop = scrollTop |
|||
requestAnimationFrame(smoothUp) |
|||
} |
|||
} |
|||
} |
|||
export function formatDate(timestamp) { |
|||
var date = new Date(timestamp * 1000);//时间戳为10位需*1000,时间戳为13位的话不需乘1000
|
|||
|
|||
var Y = date.getFullYear() + '-'; |
|||
|
|||
var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-'; |
|||
|
|||
var D = date.getDate() + ' '; |
|||
|
|||
var h = date.getHours() + ':'; |
|||
|
|||
var m = date.getMinutes() + ':'; |
|||
|
|||
var s = date.getSeconds(); |
|||
|
|||
return Y+M+D+h+m+s; |
|||
} |
|||
|
|||
@ -0,0 +1,167 @@ |
|||
//用户查询
|
|||
export interface UserQuery { |
|||
userkey: string; |
|||
usertoken: string; |
|||
} |
|||
|
|||
//用户信息
|
|||
export interface UserDetail { |
|||
//证件号码
|
|||
idcardno?: string[]; |
|||
//姓名
|
|||
name: string; |
|||
//头像url
|
|||
icon?: string; |
|||
//工号
|
|||
wmNumber: string; |
|||
//唯一识别码
|
|||
wmKey: string; |
|||
//adminorg
|
|||
adminorg:string; |
|||
|
|||
} |
|||
|
|||
//导航栏查询
|
|||
export interface NaviQuery { |
|||
atParentId: string; |
|||
userkey: String, |
|||
usertoken: String, |
|||
} |
|||
//导航栏信息
|
|||
export interface Navi{ |
|||
|
|||
atId:string; |
|||
//档案分类名称
|
|||
atTitle:string; |
|||
//档案分类状态
|
|||
atStater:string; |
|||
//档案分类父级
|
|||
atParentId:string; |
|||
//写入时间
|
|||
atTime:string; |
|||
//添加人员
|
|||
atUid:string; |
|||
//排序
|
|||
atSort:string; |
|||
//该导航栏中有无card
|
|||
hasCard:Boolean; |
|||
} |
|||
export type cardList = PageResult<Graphicform[]> |
|||
//卡片
|
|||
export interface Graphicform { |
|||
gId?:number|string; |
|||
//标题
|
|||
gTitle?:string; |
|||
//关键字
|
|||
gKey?:string; |
|||
//描述
|
|||
gDescribe?:string; |
|||
//父级
|
|||
gParent?:number|string; |
|||
//分类
|
|||
gParentSun?:number|string; |
|||
//文档来源(1:原创;2:转载)
|
|||
gSource?:number|string; |
|||
//转载地址
|
|||
gSourceUrl?:string; |
|||
//缩略图
|
|||
gThumbnail?:string; |
|||
//排序
|
|||
gSort?:number|string; |
|||
//评论设置(1:允许评论;2:禁止评论)
|
|||
gComment?:number|string; |
|||
//访问权限(1:公开;2:分厂;3:工段;4:自定义)
|
|||
gVisitStrat?:number|string; |
|||
//状态(1:草稿;2:发表;3:下架;4:删除)
|
|||
gState?:number|string; |
|||
//写入时间
|
|||
gAddTime?:number|string; |
|||
//修改时间
|
|||
gEiteTime?:number|string; |
|||
//编辑人员
|
|||
gUserKey?:number|string; |
|||
//分厂
|
|||
gBfId?:number|string; |
|||
//工段
|
|||
gWsId?:number|string; |
|||
//班组
|
|||
gTeam?:number|string; |
|||
//是否允许下载(1:允许;2:禁止)
|
|||
gDownloadState?:number|string; |
|||
//阅读量
|
|||
gRead?:number|string; |
|||
//评论数
|
|||
gComSum?:number|string; |
|||
//收藏数
|
|||
gCollectionSum?:number|string; |
|||
//点赞数
|
|||
gLikes?:number|string; |
|||
//推荐(1:推荐,2:不推荐)
|
|||
gRecommend?:number|string; |
|||
//图文详情
|
|||
gContent?:string; |
|||
//踩数量
|
|||
gStepOn?:number|string; |
|||
//自定义可见范围
|
|||
gRange?:string; |
|||
//写入分厂
|
|||
gWriteBfid?:number|string; |
|||
//正文文档名称
|
|||
gTextName?:string; |
|||
//正文文档URL
|
|||
gTestUrl?:string; |
|||
//物理地址
|
|||
gPhysicsPath?:string; |
|||
//写入人员组织
|
|||
gWriteGroup?:number|string; |
|||
//外部链接
|
|||
gOuterLink?:string; |
|||
|
|||
} |
|||
export interface PageParam extends PageQuery{ |
|||
total:number; |
|||
archivesTypeAtParentId?:string; //知识库or新闻资讯
|
|||
gParentSun?:string; //标题分类
|
|||
adminorg:string; |
|||
key:string; |
|||
userkey: string, |
|||
usertoken: string, |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 卡片list |
|||
*/ |
|||
export type graphicformList = PageResultJava<Graphicform[]> |
|||
|
|||
/** |
|||
* 分页响应对象 |
|||
*/ |
|||
interface PageResultJava<T> { |
|||
/** |
|||
* 数据列表 |
|||
*/ |
|||
list: T; |
|||
/** |
|||
* 数据总数 |
|||
*/ |
|||
total: number; |
|||
//每页条数
|
|||
pageSize:number; |
|||
//总页数
|
|||
pages:number; |
|||
//前一页
|
|||
prePage:number; |
|||
//
|
|||
size:number; |
|||
startRow:number; |
|||
//当前页
|
|||
pageNum:number; |
|||
|
|||
} |
|||
|
|||
//标题下有无内容
|
|||
export interface ShowTitle { |
|||
atIdAndGParentSun: string;//导航栏id
|
|||
hasCard:Boolean;//是否展示
|
|||
} |
|||
|
After Width: | Height: | Size: 7.3 KiB |
@ -0,0 +1,21 @@ |
|||
import { defineStore } from 'pinia' |
|||
import { ShowTitle } from '@/api/knowledge/types'; |
|||
// 第一个参数是应用程序中 store 的唯一 id
|
|||
export const useKnowledgeStore = defineStore('knowledge', { |
|||
|
|||
state: () => { |
|||
//const knowledgeTitlesShow = ref<Array<ShowTitle>>([]);
|
|||
const knowledgeTitlesShow = ref<ShowTitle[]>([]); |
|||
|
|||
return {knowledgeTitlesShow}; |
|||
|
|||
}, |
|||
getters: { |
|||
// 自动将返回类型推断为数字
|
|||
getArray(state) { |
|||
return state |
|||
}, |
|||
|
|||
}, |
|||
|
|||
}) |
|||
@ -0,0 +1,96 @@ |
|||
<script setup lang='ts'> |
|||
import { onScroll, scrollTo, formatDate } from '@/api/knowledge/scroll' |
|||
|
|||
|
|||
|
|||
|
|||
const props = defineProps({ |
|||
isShow: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
contentSource: { |
|||
type: Object |
|||
}, |
|||
}); |
|||
const emits = defineEmits(["update:isShow"]); //操作父级数据 |
|||
|
|||
/** |
|||
* 弹窗显示控制 |
|||
*/ |
|||
const boxShow = computed({ |
|||
get: () => props.isShow, |
|||
set: (val) => { |
|||
|
|||
emits("update:isShow", val); |
|||
}, |
|||
}); |
|||
|
|||
|
|||
const pdfIframeShow = ref<boolean>(false) |
|||
|
|||
/** |
|||
* 监听数据 |
|||
*/ |
|||
watch(() => props.isShow, () => { |
|||
|
|||
if (props.isShow) { |
|||
|
|||
if (props.contentSource?.gTestUrl === "" || props.contentSource?.gTestUrl == null) { |
|||
//文件是pdf |
|||
pdfIframeShow.value = false |
|||
|
|||
} else { |
|||
pdfIframeShow.value = true |
|||
} |
|||
//console.log(pdfIframeShow.value) |
|||
} |
|||
}) |
|||
onMounted(() => { |
|||
/* const gTestUrl = props.contentSource?.gTestUrl; |
|||
const gContent = props.contentSource?.gContent; */ |
|||
|
|||
}); |
|||
|
|||
|
|||
</script> |
|||
|
|||
<template> |
|||
<el-dialog v-model="boxShow" class="dialogStyle" :show-close="true"> |
|||
<template #header="{ close, titleId, titleClass }"> |
|||
<div class="my-header"> |
|||
<h4 :id="titleId" :class="titleClass" style="margin-top: 5px;">{{ props.contentSource?.gTitle }}</h4> |
|||
<!-- <h4 :id="titleId" :class="titleClass" style="margin-top: 5px;">{{ props.contentSource?.gContent }}</h4> --> |
|||
</div> |
|||
</template> |
|||
<div style="padding-bottom: 20px;"><span>{{ formatDate(props.contentSource?.gAddTime) }}</span></div> |
|||
<iframe v-if="pdfIframeShow" :src="props.contentSource?.gTestUrl" frameborder="0" |
|||
style=" z-index: 1000;height: 680px;width: 850px"></iframe> |
|||
<div v-html="props.contentSource?.gContent" style="height: auto;width: auto;"></div> |
|||
|
|||
<h5>评论区</h5> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
|
|||
|
|||
<style> |
|||
.dialogStyle { |
|||
top:-9.9%; |
|||
height: auto; |
|||
width: auto; |
|||
max-width: 1000px; |
|||
|
|||
} |
|||
|
|||
.my-header { |
|||
display: flex; |
|||
flex-direction: row; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.el-dialog__body { |
|||
margin-top: 0% !important; |
|||
padding-top: 0% !important; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,32 @@ |
|||
<script lang='ts' setup> |
|||
import { scrollTo } from '@/api/knowledge/scroll' |
|||
const showli = ref(true); |
|||
const props = defineProps({ |
|||
oneli: { |
|||
type: Object, |
|||
|
|||
}, |
|||
|
|||
index: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
active: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
knowledgeStore: { |
|||
type: Object, |
|||
}, |
|||
fatherisReady1: { |
|||
type: Number, |
|||
} |
|||
}) |
|||
|
|||
</script> |
|||
<template> |
|||
<li :class="{ active: active === index }" @click="scrollTo(index)" v-if="showli"> |
|||
{{ oneli?.atTitle }} |
|||
</li> |
|||
</template> |
|||
<style></style> |
|||
@ -0,0 +1,287 @@ |
|||
<script lang='ts' setup> |
|||
import { useUserStore } from "@/store/modules/user" |
|||
import { ref, watch } from 'vue' |
|||
import { getTuijian } from '@/api/knowledge/index' |
|||
import KnowledgeContent from '@/views/knowledge/knowledge/components/KnowledgeContent.vue' |
|||
import { UserDetail, NaviQuery, Navi, Graphicform, PageParam, ShowTitle } from '@/api/knowledge/types' |
|||
import { formatDate } from '@/api/knowledge/scroll' |
|||
import errimg from '@/assets/404_images/imgNotFound.png' |
|||
import { useKnowledgeStore } from "@/store/modules/knowledge" |
|||
|
|||
const showArea = ref(true); |
|||
|
|||
const props = defineProps({ |
|||
liContent: { |
|||
type: Object, |
|||
|
|||
}, |
|||
routerUrl: { |
|||
type: String, |
|||
}, |
|||
|
|||
index: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
active: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
fatherisReady: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
|
|||
}) |
|||
|
|||
const userStore = useUserStore(); |
|||
const { userKey, userToken } = userStore; |
|||
const userDetail = ref<UserDetail>({ |
|||
//证件号码 |
|||
idcardno: ["1", "2"], |
|||
//姓名 |
|||
name: 'a', |
|||
//头像url |
|||
icon: 'b', |
|||
//工号 |
|||
wmNumber: '2', |
|||
//唯一识别码 |
|||
wmKey: "1", |
|||
//adminorg |
|||
adminorg: "9999", |
|||
}); |
|||
const tuijianPage = ref<Graphicform[]>(); |
|||
|
|||
|
|||
//navi查询参数 |
|||
const naviQueryParam = reactive<NaviQuery>({ |
|||
atParentId: "",//知识库 |
|||
userkey: userKey, |
|||
usertoken: userToken, |
|||
}); |
|||
const pageParamTuijian = reactive<PageParam>({ |
|||
total: 0, |
|||
page: 1, |
|||
pagesize: 9, |
|||
archivesTypeAtParentId: "", //知识库or新闻资讯 |
|||
gParentSun: "", |
|||
//唯一识别码 |
|||
key: String(userDetail.value.wmKey), |
|||
//adminorg |
|||
adminorg: String(userDetail.value.adminorg), |
|||
userkey: userKey, |
|||
usertoken: userToken, |
|||
|
|||
}) |
|||
|
|||
function errorImg(e: any) { |
|||
e.srcElement.src = errimg; |
|||
//这一句没用,如果默认图片的路径错了还是会一直闪屏,在方法的前面加个.once只让它执行一次也没用 |
|||
e.srcElement.onerror = null; //防止闪图 |
|||
} |
|||
|
|||
watch(() => [props.fatherisReady, props.liContent, props.routerUrl], (newVal, oldVal) => { |
|||
//console.log(newVal, oldVal); // [11, 22], [1, 2] |
|||
const routerUrl = oldVal[2] as String; |
|||
const liContent = newVal[1] as any; |
|||
//console.log(newVal[1]) |
|||
//console.log(oldVal[2]) |
|||
|
|||
//console.log(routerUrl) |
|||
if (routerUrl?.endsWith("index")) {//此时页面为知识库 |
|||
naviQueryParam.atParentId = '16213848089876281' |
|||
pageParamTuijian.archivesTypeAtParentId = '16213848089876281' |
|||
} else if (routerUrl?.endsWith("news")) {//此时页面为新闻资讯 |
|||
naviQueryParam.atParentId = '16213847972425134' |
|||
pageParamTuijian.archivesTypeAtParentId = '16213847972425134' |
|||
} |
|||
|
|||
pageParamTuijian.gParentSun = liContent.atId; |
|||
//推荐 |
|||
if (props.liContent?.hasCard == true) { |
|||
//console.log(props.liContent?.hasCard) |
|||
getTuijian(pageParamTuijian) |
|||
.then(({ data }) => { |
|||
tuijianPage.value = data.list |
|||
//console.log(tuijianPage.value) |
|||
pageParamTuijian.page = data.pageNum |
|||
pageParamTuijian.total = data.total |
|||
if (pageParamTuijian.total > 0) { |
|||
showCards.value = 1; |
|||
} |
|||
const KnowledgeStore = useKnowledgeStore(); |
|||
|
|||
|
|||
if (tuijianPage.value.length > 0) { |
|||
//本标题下有数据 |
|||
KnowledgeStore.$patch((state) => { |
|||
state.knowledgeTitlesShow.push({ atIdAndGParentSun: liContent.atId, hasCard: true }) |
|||
}) |
|||
showArea.value = true; |
|||
} else { |
|||
KnowledgeStore.$patch((state) => { |
|||
state.knowledgeTitlesShow.push({ atIdAndGParentSun: liContent.atId, hasCard: false }) |
|||
|
|||
}) |
|||
//showArea.value = false; |
|||
} |
|||
}); |
|||
} |
|||
}) |
|||
|
|||
function handleCurrentChange() { |
|||
|
|||
getTuijian(pageParamTuijian) |
|||
.then(({ data }) => { |
|||
tuijianPage.value = data.list |
|||
pageParamTuijian.page = data.pageNum |
|||
pageParamTuijian.total = data.total |
|||
}); |
|||
} |
|||
|
|||
|
|||
const showCards = ref(0) |
|||
|
|||
|
|||
//dialog |
|||
const cardContentSource = ref<Graphicform>({}); |
|||
const showContentBox = ref(false); //详情弹窗 |
|||
function showContentDialog(item: any) { |
|||
|
|||
showContentBox.value = true; |
|||
cardContentSource.value = item; |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
</script> |
|||
<template> |
|||
<div class="models "> |
|||
<KnowledgeContent v-model:isShow="showContentBox" :contentSource="cardContentSource"></KnowledgeContent> |
|||
<div class="model-title"> |
|||
<h3>{{ props.liContent?.atTitle }}</h3> |
|||
|
|||
</div> |
|||
<div v-show="!showCards" style="text-align: center;padding-top: 5%;">暂无数据</div> |
|||
<div class="grid-tuijian" v-show="showCards"> |
|||
|
|||
|
|||
<div v-for="(item, index) in tuijianPage" :key="index" class="tuijian-card" @click="showContentDialog(item)"> |
|||
<img style="width: 170px; height: 126px;border-radius:8px;margin-top: 4px; margin-left: 4px;" |
|||
referrerpolicy="no-referrer" :src="item.gThumbnail" fit="fill" loading="lazy" @error="errorImg($event)" /> |
|||
|
|||
<div class="card-right"> |
|||
<span class="card-title" :title=item.gTitle>{{ item.gTitle }}</span> |
|||
<span class="card-text" :title="item.gDescribe">{{ item.gDescribe }}</span> |
|||
|
|||
<span class="time-span"><span class="fa fa-clock-o"></span>{{ formatDate(item.gAddTime) }}</span> |
|||
|
|||
<span class="myicons"> |
|||
<span class="fa fa-star-o"></span>收藏(<span>{{ item.gCollectionSum }}</span>) <span |
|||
class="fa fa-thumbs-o-up"></span>赞(<span>{{ |
|||
item.gLikes }}</span>) <span class="fa fa-thumbs-o-down"></span>踩(<span>{{ item.gStepOn }}</span>) |
|||
<span class="fa fa-eye">阅读</span>(<span>{{ item.gRead }}</span>) |
|||
</span> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<el-pagination class="pagi" v-model:current-page="pageParamTuijian.page" v-if="pageParamTuijian.total > 0" |
|||
v-model:page-size="pageParamTuijian.pagesize" layout="prev, pager, next, jumper" :total="pageParamTuijian.total" |
|||
@current-change="handleCurrentChange" /> |
|||
</div> |
|||
</template> |
|||
<style> |
|||
.models { |
|||
width: 100%; |
|||
min-height: 200px; |
|||
|
|||
|
|||
} |
|||
|
|||
.model-title { |
|||
height: 30px; |
|||
} |
|||
|
|||
|
|||
|
|||
.grid-tuijian { |
|||
/* border-top: solid 1px; */ |
|||
display: grid; |
|||
grid-template-columns: repeat(auto-fill, 484px); |
|||
gap: 10px; |
|||
grid-auto-flow: row dense; |
|||
|
|||
} |
|||
|
|||
.tuijian-card { |
|||
display: flex; |
|||
width: 481px; |
|||
height: 140px; |
|||
padding: 3px; |
|||
border-radius: 8px; |
|||
flex-direction: row; |
|||
flex-wrap: wrap; |
|||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; |
|||
} |
|||
|
|||
.mycarousel { |
|||
grid-row-start: 1; |
|||
grid-row-end: 3; |
|||
border-radius: 15px; |
|||
} |
|||
|
|||
.card-right { |
|||
display: flex; |
|||
width: 260px; |
|||
flex-direction: column; |
|||
flex-wrap: wrap; |
|||
padding-left: 8px; |
|||
} |
|||
|
|||
.card-title { |
|||
height: 1.5em !important; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
overflow: hidden; |
|||
-webkit-line-clamp: 1; |
|||
} |
|||
|
|||
.card-text { |
|||
margin-top: 2px; |
|||
margin-bottom: 2px; |
|||
height: 3.1em; |
|||
font-size: 14px; |
|||
color: #909399; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
overflow: hidden; |
|||
-webkit-line-clamp: 2; |
|||
} |
|||
|
|||
.time-span { |
|||
height: 1.5em; |
|||
align-self: end; |
|||
margin-top: auto; |
|||
font-size: 13px; |
|||
margin-right: 5px; |
|||
color: #909399; |
|||
|
|||
|
|||
} |
|||
|
|||
.myicons { |
|||
align-self: end; |
|||
margin-right: 5px; |
|||
font-size: 13px; |
|||
color: #909399; |
|||
} |
|||
|
|||
.el-pagination { |
|||
margin-top: 20px; |
|||
margin-bottom: 10px; |
|||
justify-content: center; |
|||
|
|||
} |
|||
</style> |
|||
@ -0,0 +1,357 @@ |
|||
<script lang='ts' setup> |
|||
import { useUserStore } from "@/store/modules/user" |
|||
|
|||
import { ref } from 'vue' |
|||
import { getUserDetail, getZxxyNavis, getTuijian, getCarousel } from '@/api/knowledge/index' |
|||
import Archivestype from '@/views/knowledge/knowledge/components/archivestype.vue' |
|||
import Navili from './components/Navili.vue' |
|||
import KnowledgeContent from './components/KnowledgeContent.vue' |
|||
import { UserQuery, UserDetail, NaviQuery, Navi, Graphicform, PageParam } from '@/api/knowledge/types' |
|||
import { onScroll, scrollTo, formatDate } from '@/api/knowledge/scroll' |
|||
import { useRouter } from 'vue-router' |
|||
import errimg from '@/assets/404_images/imgNotFound.png' |
|||
|
|||
const active = ref(0); // 当前激活的导航索引 |
|||
|
|||
|
|||
const userStore = useUserStore(); |
|||
const { userKey, userToken } = userStore; |
|||
|
|||
|
|||
const userDetail = ref<UserDetail>({ |
|||
//证件号码 |
|||
idcardno: ["1", "2"], |
|||
//姓名 |
|||
name: 'a', |
|||
//头像url |
|||
icon: 'b', |
|||
//工号 |
|||
wmNumber: '2', |
|||
//唯一识别码 |
|||
wmKey: "1", |
|||
//adminorg |
|||
adminorg: "9999", |
|||
}); |
|||
const tuijianPage = ref<Graphicform[]>(); |
|||
|
|||
const naviList = ref<Navi[]>(); |
|||
const naviList1 = ref<Navi[]>(); |
|||
//用户信息查询参数 |
|||
const userQueryParam = reactive<UserQuery>({ |
|||
userkey: userKey, |
|||
usertoken: userToken, |
|||
}); |
|||
//navi查询参数 |
|||
const naviQueryParam = reactive<NaviQuery>({ |
|||
atParentId: "",//知识库 |
|||
userkey: userKey, |
|||
usertoken: userToken, |
|||
}); |
|||
const pageParamTuijian = reactive<PageParam>({ |
|||
total: 0, |
|||
page: 1, |
|||
pagesize: 7, |
|||
archivesTypeAtParentId: "", //知识库or新闻资讯 |
|||
gParentSun: "", |
|||
//唯一识别码 |
|||
key: String(userDetail.value.wmKey), |
|||
//adminorg |
|||
adminorg: String(userDetail.value.adminorg), |
|||
userkey: userKey, |
|||
usertoken: userToken, |
|||
|
|||
}) |
|||
const carousel = ref<Graphicform[]>(); |
|||
function errorImg(e: any) { |
|||
e.srcElement.src = errimg; |
|||
//这一句没用,如果默认图片的路径错了还是会一直闪屏,在方法的前面加个.once只让它执行一次也没用 |
|||
e.srcElement.onerror = null; //防止闪图 |
|||
} |
|||
const fatherisReady = ref(0); |
|||
|
|||
const router = useRouter() |
|||
const routerUrl = toRaw(router).currentRoute.value.fullPath |
|||
onBeforeMount(() => { |
|||
//当前登录用户详细信息 |
|||
getUserDetail(userQueryParam) |
|||
.then(({ data }) => { |
|||
userDetail.value = data |
|||
}); |
|||
|
|||
}) |
|||
|
|||
|
|||
onMounted(() => { |
|||
// 监听滚动事件 |
|||
window.addEventListener('scroll', jsScroll, false) |
|||
|
|||
if (routerUrl.endsWith("index")) {//此时页面为知识库 |
|||
naviQueryParam.atParentId = '16213848089876281' |
|||
pageParamTuijian.archivesTypeAtParentId = '16213848089876281' |
|||
} else if (routerUrl.endsWith("news")) {//此时页面为新闻资讯 |
|||
naviQueryParam.atParentId = '16213847972425134' |
|||
pageParamTuijian.archivesTypeAtParentId = '16213847972425134' |
|||
} |
|||
getZxxyNavis(naviQueryParam) |
|||
.then(({ data }) => { |
|||
naviList.value = data |
|||
}).finally(() => { |
|||
fatherisReady.value = 100; |
|||
}) |
|||
//推荐 |
|||
getTuijian(pageParamTuijian) |
|||
.then(({ data }) => { |
|||
tuijianPage.value = data.list |
|||
pageParamTuijian.page = data.pageNum |
|||
pageParamTuijian.total = data.total |
|||
}); |
|||
getCarousel(pageParamTuijian) |
|||
.then(({ data }) => { |
|||
carousel.value = data.list |
|||
}); |
|||
}); |
|||
|
|||
|
|||
function jsScroll() { |
|||
active.value = onScroll(); |
|||
} |
|||
|
|||
onUnmounted(() => { |
|||
// 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错 |
|||
window.removeEventListener('scroll', onScroll) |
|||
}); |
|||
function handleCurrentChange() { |
|||
|
|||
getTuijian(pageParamTuijian) |
|||
.then(({ data }) => { |
|||
tuijianPage.value = data.list |
|||
pageParamTuijian.page = data.pageNum |
|||
pageParamTuijian.total = data.total |
|||
}); |
|||
|
|||
} |
|||
|
|||
//dialog |
|||
const cardContentSource = ref<Graphicform>({}); |
|||
const showContentBox = ref(false); //详情弹窗 |
|||
|
|||
function showContentDialog(item: any) { |
|||
showContentBox.value = true; |
|||
cardContentSource.value = item; |
|||
} |
|||
|
|||
|
|||
</script> |
|||
<template> |
|||
<div class="app-container"> |
|||
<KnowledgeContent v-model:isShow="showContentBox" :contentSource="cardContentSource"></KnowledgeContent> |
|||
<!-- 内容区域 --> |
|||
<div class="content"> |
|||
|
|||
<div class="models "> |
|||
|
|||
<div class="model-title"> |
|||
<h3>推荐</h3> |
|||
|
|||
</div> |
|||
<div class="grid-tuijian"> |
|||
<el-carousel indicator-position="outside" class="mycarousel" arrow="always"> |
|||
<el-carousel-item v-for="(item, index) in carousel" :key="index"> |
|||
|
|||
<img style="width: 495px; height: 300px;border-radius:16px;margin-top: 4px; margin-left: 4px;" |
|||
referrerpolicy="no-referrer" :src="item.gThumbnail" fit="fill" loading="lazy" @error="errorImg($event)" /> |
|||
</el-carousel-item> |
|||
</el-carousel> |
|||
|
|||
<div v-for="(item, index) in tuijianPage" :key="index" class="tuijian-card" @click="showContentDialog(item)"> |
|||
<img style="width: 170px; height: 126px;border-radius:8px;margin-top: 4px; margin-left: 4px;" |
|||
referrerpolicy="no-referrer" :src="item.gThumbnail" fit="fill" loading="lazy" @error="errorImg($event)" /> |
|||
|
|||
<div class="card-right"> |
|||
<span class="card-title" :title=item.gTitle>{{ item.gTitle }}</span> |
|||
<span class="card-text" :title=item.gDescribe>{{ item.gDescribe }}</span> |
|||
|
|||
<span class="time-span"><span class="fa fa-clock-o"></span>{{ formatDate(item.gAddTime) }}</span> |
|||
|
|||
<span class="myicons"> |
|||
<span class="fa fa-star-o"></span>收藏(<span>{{ item.gCollectionSum }}</span>) <span |
|||
class="fa fa-thumbs-o-up"></span>赞(<span>{{ |
|||
item.gLikes }}</span>) <span class="fa fa-thumbs-o-down"></span>踩(<span>{{ item.gStepOn }}</span>) |
|||
<span class="fa fa-eye">阅读</span>(<span>{{ item.gRead }}</span>) |
|||
</span> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<el-pagination class="pagi" v-model:current-page="pageParamTuijian.page" v-if="pageParamTuijian.total > 0" |
|||
v-model:page-size="pageParamTuijian.pagesize" layout="prev, pager, next, jumper" :total="pageParamTuijian.total" |
|||
@current-change="handleCurrentChange" /> |
|||
</div> |
|||
<!-- 各知识/新闻分区 --> |
|||
|
|||
<template v-for="(item, index) in naviList"> |
|||
<Archivestype :liContent=item :index=(index) :fatherisReady="fatherisReady" :routerUrl="routerUrl"></Archivestype> |
|||
</template> |
|||
|
|||
|
|||
|
|||
|
|||
</div> |
|||
|
|||
<!-- 导航区域 --> |
|||
|
|||
<ul class="navs"> |
|||
<li :class="{ active: active === 0 }" @click="scrollTo(0)"> |
|||
推荐 |
|||
</li> |
|||
|
|||
<template v-for="(item, index) in naviList"> |
|||
<Navili :class="{ active: active === index+1 }" :oneli=item :index=(index+1) v-if="item.hasCard" :active=active |
|||
@click="scrollTo(index + 1)"></Navili> |
|||
</template> |
|||
|
|||
</ul> |
|||
</div> |
|||
</template> |
|||
|
|||
|
|||
|
|||
<style scoped> |
|||
.content { |
|||
background-color: white; |
|||
width: 89.1%; |
|||
margin-left: 190px; |
|||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; |
|||
border-radius: 5px; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* 导航栏的样式 */ |
|||
.navs { |
|||
|
|||
|
|||
|
|||
width: 192px; |
|||
position: fixed; |
|||
height: auto; |
|||
top: 95px; |
|||
|
|||
} |
|||
|
|||
.navs li { |
|||
|
|||
text-align: center; |
|||
line-height: 3; |
|||
font-size: 15.5px; |
|||
color: #909399; |
|||
background-color: white; |
|||
margin-right: 15px; |
|||
} |
|||
|
|||
.navs li:hover { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
/* 当导航被点亮后改变颜色 */ |
|||
.navs .active { |
|||
color: #409EFF; |
|||
|
|||
} |
|||
|
|||
.model-title { |
|||
margin-top: -9px; |
|||
height: 30px; |
|||
} |
|||
|
|||
.grid-tuijian { |
|||
|
|||
|
|||
display: grid; |
|||
grid-template-columns: repeat(auto-fill, 484px); |
|||
gap: 10px; |
|||
grid-auto-flow: row dense; |
|||
|
|||
} |
|||
|
|||
.tuijian-card { |
|||
display: flex; |
|||
width: 481px; |
|||
height: 140px; |
|||
padding: 3px; |
|||
border-radius: 8px; |
|||
flex-direction: row; |
|||
flex-wrap: wrap; |
|||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px; |
|||
} |
|||
|
|||
.mycarousel { |
|||
|
|||
grid-row-start: 1; |
|||
grid-row-end: 3; |
|||
border-radius: 15px; |
|||
width: 480px; |
|||
height: 290px; |
|||
} |
|||
|
|||
.card-right { |
|||
display: flex; |
|||
width: 300px; |
|||
flex-direction: column; |
|||
flex-wrap: wrap; |
|||
padding-left: 8px; |
|||
} |
|||
|
|||
.card-title { |
|||
|
|||
|
|||
height: 1.5em !important; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
overflow: hidden; |
|||
-webkit-line-clamp: 1; |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
.card-text { |
|||
margin-top: 2px; |
|||
margin-bottom: 2px; |
|||
height: 3.1em; |
|||
font-size: 14px; |
|||
color: #909399; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
overflow: hidden; |
|||
-webkit-line-clamp: 2; |
|||
} |
|||
|
|||
.time-span { |
|||
height: 1.5em; |
|||
align-self: end; |
|||
margin-top: auto; |
|||
font-size: 13px; |
|||
margin-right: 5px; |
|||
color: #909399; |
|||
|
|||
|
|||
} |
|||
|
|||
.myicons { |
|||
|
|||
align-self: end; |
|||
margin-right: 5px; |
|||
font-size: 13px; |
|||
color: #909399; |
|||
} |
|||
|
|||
.el-pagination { |
|||
margin-top: 20px; |
|||
margin-bottom: 10px; |
|||
justify-content: center; |
|||
|
|||
} |
|||
</style> |
|||
|
|||
Loading…
Reference in new issue