提交合并后的所有文件

This commit is contained in:
daihh
2022-12-21 18:07:13 +08:00
173 changed files with 12994 additions and 5791 deletions

160
components/at-my/at-my.vue Normal file
View File

@@ -0,0 +1,160 @@
<template>
<view class="at-my-com">
<view class="at-my-index" v-for="at in items">
<view class="at-who">
<view class="who-img">
<author-img :avatar="at.authorInfo.avatar" :sex="at.authorInfo.sex"></author-img>
</view>
<view class="who-name">
<view class="name-info">
{{at.sysCreateBy}} <view class="who-time">{{at.sysCreateTime.split(' ')[0]}}</view>
</view>
<view class="info-text">
<text class="name-text-at">@</text>
{{filterObjType(at.objType)}}不错你也来看看吧
</view>
</view>
</view>
<view class="at-title-box" @click="toArticleDetail(at)">
<view class="at-name">{{at.title}}</view>
</view>
</view>
</view>
</template>
<script>
import apiQa from '@/api/modules/qa.js'
import apiComments from '../../api/modules/comments.js';
export default {
props:{
items:{
type:Array,
}
},
data() {
return {
// data:[],//拿到的数据
// total:0,//总条数
// loadStatus:'more',//more,loading,noMore
// query:{
// pageIndex:1,//当前页
// type:null,//当前只限于文章
// pageSize:10,//条数
// },//查询条件
}
},
// onLoad() {
// this.findData(true);
// },
// onPullDownRefresh() {
// this.onReachBottom();
// },
// onReachBottom() {
// console.log('111111')
// this.loadStatus='loading';//more,loading,noMore
// if(this.data.length<this.total){
// this.query.pageIndex++;
// this.findData(false);
// this.loadStatus='more'
// }else{
// this.loadStatus='noMore'
// }
// },
mounted() {
// this.findData(true);
},
methods: {
filterObjType(objType){
switch(objType){
case 1:{
return '课程'
}
case 2:{
return '文章'
}
case 3:{
return '案例'
}
case 4:{
return '问答'
}
}
},
toArticleDetail(item) {
if(item.objType == 2){
uni.navigateTo({
url: '/pages/resource/articeDetail?id=' + item.objId
});
}else if(item.objType == 1){
uni.navigateTo({
url: '/pages/resource/courseDetail?id=' + item.objId
});
}else if(item.objType == 4){
uni.navigateTo({
url: '/pages/resource/qaDetail?id=' + item.objId
});
}
},
}
}
</script>
<style scoped lang="scss">
.at-my-com{
padding: 0 32upx;
.at-my-index{
padding: 60upx 0 50upx 0;
border-bottom: 2upx solid rgba(153,153,153,0.1);
.at-who{
display: flex;
.who-img{
margin-right: 20upx;
}
.who-name{
width: 100%;
font-size: 28upx;
.name-info{
font-weight: 600;
color: #333333;
}
.who-time{
float: right;
font-weight: 400;
font-size: 24upx;
color: #999999;
}
.info-text{
margin-top: 8upx;
color: #333333;
.name-text-at{
margin-right: 20upx;
color: #387DF7;
}
}
}
}
.at-title-box{
margin-top: 22upx;
padding: 40upx 60upx;
background: #F6F6F6;
font-size: 32upx;
font-weight: 600;
color: #333333;
}
.at-name{
word-break:break-all;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;-webkit-line-clamp: 1;
}
}
}
</style>

View File

@@ -0,0 +1,120 @@
<template>
<view class="item-author">
<view>
<u-avatar v-if="avatar && avatar!=''" shape="circle" :size="size" :src="fileBaseUrl + avatar" ></u-avatar>
<view v-else>
<view v-if="sex == null" class="peo" :style="{width:width,height:height}">
<image src="../../static/images/default.png" alt="">
</view>
<view v-else :style="{width:width,height:height}">
<view class="peo" v-if="sex == 1 "><image src="../../static/images/man.png" alt=""></view>
<view class="peo" v-else-if="sex==2 "><image src="../../static/images/woman.png" alt=""></view>
<view class="peo" v-else><image src="../../static/images/man.png" alt=""></view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props:{
avatar:{
type:String,
default:''
},
name:{
type:String,
default:''
},
showInfo:{
type:Boolean,
default:false
},
showCode:{
type:Boolean,
default:false
},
info:{
type:String,
default:''
},
sex:{
type:Number,
default:null
},
size:{
type:Number,
default:40
},
width:{
type:String,
default:'40px'
},
height:{
type:String,
default:'40px'
},
},
data(){
return {
fileBaseUrl:this.$config.fileUrl,
userAvatar:'',
// sex:null,
}
},
computed:{
avatarText(){
let text=this.name;
if(text){
let len=text.length;
if(text.length>2){
text=text.substring(len-2);
}
}
return text;
}
},
mounted() {
this.userAvatar=this.avatar;
},
watch:{
},
methods:{
}
}
</script>
<style lang="scss" scoped>
.peo{
width: 100%;
height: 100%;
image{
width: 100%;
height: 100%;
border-radius: 50%;
vertical-align: middle;
}
}
.uavatar{
border:1px solid #73adfe;
background-color: #d9e9ff;
color:#73adfe;
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
.uavatar-scale{
transform:scale(0.8);
}
}
.item-author{
font-size: 14upx;
display: inline-block;
vertical-align: middle;
}
</style>

View File

@@ -1,17 +1,17 @@
<template>
<view class="item-author" style="display: flex;line-height: 25px;">
<view>
<u-avatar v-if="avatar && avatar!=''" shape="square" :size="25" :src="avatar" ></u-avatar>
<u-avatar v-if="avatar && avatar!=''" shape="circle" :size="width" :src="fileUrl+avatar" ></u-avatar>
<!-- <u-avatar v-else :size="25" icon="account" shape="square"></u-avatar> -->
<view v-else>
<view v-if="sex == null" class="peo"></view>
<view v-else>
<view v-else :style="{width:width,height:height}">
<view class="peo" v-if="sex === 1 "><image src="../../static/images/man.png" alt=""></view>
<view class="peo" v-else><image src="../../static/images/woman.png" alt=""></view>
</view>
</view>
</view>
<view style="padding-left:10upx;padding-top: 4upx;font-size: 26rpx;color: #666666;">{{name}}</view>
<view class="author-name">{{name}}</view>
<!-- <view v-if="showInfo && info!=''" style="padding-left: 10upx;padding-top: 10upx;">({{info}})</view> -->
<!-- ({{info}}) -->
</view>
@@ -43,10 +43,19 @@
sex:{
type:Number,
default:null
}
},
width:{
type:String,
default:'20px'
},
height:{
type:String,
default:'20px'
},
},
data(){
return {
fileUrl:this.$config.fileUrl,
userAvatar:'',
// sex:null,
}
@@ -87,8 +96,8 @@
<style lang="scss" scoped>
.peo{
width: 25px;
height: 25px;
width: 100%;
height: 100%;
image{
width: 100%;
height: 100%;
@@ -113,5 +122,11 @@
font-size: 14upx;
display: flex;
align-items: center;
.author-name{
padding-left:16upx;
padding-top: 4upx;
font-size: 28upx;
color: #666666;
}
}
</style>

View File

@@ -1,19 +1,19 @@
<template>
<view class="item-author" style="display: flex;">
<view>
<u-avatar shape="circle" v-if="data.avatar && data.avatar!=''" :size="25" :src="data.avatar"></u-avatar>
<view v-else :size="25" :sex="data.sex" random-bg-color >
<u-avatar shape="circle" v-if="data.avatar && data.avatar!=''" :size="size" :src="data.avatar"></u-avatar>
<view v-else :sex="data.sex" random-bg-color >
<view v-if="data.sex == null" class="peo"></view>
<view v-else>
<view class="peo" v-if="data.sex === 1 "><image src="../../static/images/man.png" alt=""></view>
<view class="peo" v-else><image src="../../static/images/woman.png" alt=""></view>
<view :style="{width:width,height:height}" class="peo" v-if="data.sex === 1 "><image src="../../static/images/man.png" alt=""></view>
<view :style="{width:width,height:height}" class="peo" v-else><image src="../../static/images/woman.png" alt=""></view>
</view>
</view>
<!-- <u-avatar v-else :size="25" random-bg-color :text="data.name" shape="square"></u-avatar> -->
<!-- <view v-else class="uavatar"><view class="uavatar-scale"> {{avatarText}}</view></view> -->
<!-- <u-avatar v-else :size="25" icon="account" shape="square"></u-avatar> -->
</view>
<view style="padding-left:10upx;padding-top: 4upx;font-size: 26upx;color: #666666;">{{data.name || data.sysCreateBy}}</view>
<view style="padding-left:10upx;padding-top: 4upx;font-size: 28upx;color: #666666;">{{data.name || data.sysCreateBy}}</view>
<!-- <view v-if="showCode && data.code!=''" style="padding-left: 10upx;padding-top: 10upx;">({{data.code}})</view> -->
</view>
</template>
@@ -36,7 +36,19 @@
showCode:{
type:Boolean,
default:true
}
},
size:{
type:Number,
default:24
},
width:{
type:String,
default:'24px'
},
height:{
type:String,
default:'24px'
},
},
data(){
return {
@@ -65,8 +77,10 @@
<style lang="scss" scoped >
.peo{
width: 25px;
height: 25px;
width: 100%;
height: 100%;
// width: 25px;
// height: 25px;
image{
width: 100%;
height: 100%;

View File

@@ -4,8 +4,8 @@
<view class="comments">
<view v-if="showTop" class="comments-top">
<view>
<text style="font-size: 30upx;font-weight: 500;">评论 </text>
<text style="font-size: 30upx;padding-left: 6upx;color: #000000;"> ( {{total}} )</text></view>
<text style="font-size: 32upx;font-weight: 500;">评论 </text>
<text style="font-size: 28upx;padding-left: 20upx;color: #333;font-weight: 400;"> ({{total}})</text></view>
<view>
<!-- <view v-if="showShare" class="share-btn" @click="addShare">
<view class="share-btn-icon"><img src="/static/images/icon/share.png" alt=""></view>
@@ -17,51 +17,70 @@
<!--内容确定了这部分样式要移到class中-->
<view v-for="(comm,commidx) in list" :key="commidx" class="comment">
<view class="comment-top">
<view style="display: flex;">
<author :showInfo="true" :data="comm"></author>
<!-- <author-info :avatar="comm.avatar" :name="comm.sysCreateBy"></author-info> -->
</view>
<view class="comment-time">
<time-show :time="comm.sysCreateTime"></time-show>
</view>
<author-img :avatar="comm.avatar" :sex="comm.sex" width="30px" height="30px" :size="30"></author-img>
<text style="font-size: 28upx;ont-weight: 500;color: #333333;margin-left: 22upx;">{{comm.sysCreateBy}}</text>
</view>
<view class="comment-body">
<view class="comment-content" v-html="comm.content"></view>
<view class="comment-btns">
<view>
<view class="comment-time">
<time-show :time="comm.sysCreateTime"></time-show>
</view>
<view class="" style="display: flex;">
<view style="font-size: 12px;color: #999999;line-height: 60upx;" @click="openInput(commidx)">
<image style="width: 36upx;height: 36upx;vertical-align: middle;margin-right: 10upx;" src="../../static/images/icon/bar-comment.png" size="24"></image>回复
<!-- <u-icon @click="openInput(commidx)" name="chat" color="#979797" size="18" label="回复"></u-icon> -->
</view>
<interact-bar :pageType="objType" :pageParams="objId" :type="praisesType" :data="comm" :comments="false" :favorites="false"></interact-bar>
</view>
<!-- <view>
<u-icon @click="openInput(commidx)" name="chat" color="#979797" size="18" label="回复"></u-icon>
</view>
<view>
</view> -->
<!-- <view>
<u-icon @click="openBtns(commidx,-1,comm)" name="more-dot-fill" size="20"></u-icon>
</view>
</view> -->
</view>
<view v-if="comm.replyList && comm.replyList.length>0" class="comment-replys">
<view v-for="(reply,replyIdx) in comm.replyList" :key="replyIdx" class="comment">
<view v-for="(reply,replyIdx) in comm.replyList" :key="replyIdx" class="comment" v-if="comm.showAll || replyIdx<2">
<view class="comment-top">
<view style="display: flex;">
<author v-if="reply" :showInfo="true" :data="reply"></author>
<!-- <author-info :avatar="reply.avatar" :name="reply.sysCreateBy"></author-info> -->
<!-- <u-avatar shape="square" icon="account" :size="26" :src="reply.avatar"></u-avatar>
<text style="margin-left: 10upx;"> {{reply.sysCreateBy}}</text> -->
<text style="padding-left: 16upx;padding-top: 6upx;color: #979797;"> 回复 </text>
<text style="padding-left: 16upx;padding-top: 6upx;color: #979797;font-size: 20upx;"> 回复 </text>
<text style="padding-left: 16upx;padding-top: 6upx;font-size: 26upx;">{{reply.replyName}}</text>
</view>
<view class="comment-time">
<time-show :time="reply.sysCreateTime"></time-show>
</view>
</view>
<view class="comment-body">
<view class="comment-body" style="margin-left: 0;padding-left: 50upx;">
<view class="comment-content" v-html="reply.content"></view>
<view class="comment-btns">
<view>
<u-icon @click="openInput(commidx,replyIdx)" name="chat" color="#979797" size="18" label="回复"></u-icon>
<view class="" style="display: flex;justify-content: space-between;">
<view class="comment-time">
<time-show :time="reply.sysCreateTime"></time-show>
</view>
<view>
<u-icon @click="openBtns(commidx,replyIdx,reply)" name="more-dot-fill" size="20"></u-icon>
<view class="comment-btns" style="line-height: 60upx;">
<view style="font-size: 12px;color: #999999;" @click="openInput(commidx,replyIdx)">
<image style="width: 36upx;height: 36upx;vertical-align: middle;margin-right: 10upx;" src="../../static/images/icon/bar-comment.png" size="24"></image>回复
<!-- <u-icon @click="openInput(commidx)" name="chat" color="#979797" size="18" label="回复"></u-icon> -->
</view>
<interact-bar :pageType="objType" :pageParams="objId" :data="reply" :type="praisesType" :comments="false" :favorites="false"></interact-bar>
<!-- <view>
<u-icon @click="openInput(commidx,replyIdx)" name="chat" color="#979797" size="18" label="回复"></u-icon>
</view>
<view>
<u-icon @click="openBtns(commidx,replyIdx,reply)" name="more-dot-fill" size="20"></u-icon>
</view> -->
</view>
</view>
</view>
</view>
<view v-if="comm.replyList.length>2" class="view-all-com" @click="loadReplyMore(comm)">
{{comm.showAll ? '收起':`查看全部${comm.replyList.length}条评论 >`}}
</view>
</view>
</view>
</view>
@@ -75,12 +94,12 @@
<view v-if="total>pageSize">
<uni-load-more :status="loadStatus"></uni-load-more>
</view>
<u-popup :show="inputShow" @close="closeInput">
<u-popup :show="inputShow" @close="closeInput" :round="16">
<view>
<view style="display: flex;">
<view style="flex: 1;"><u--textarea :height="150" v-model="inputValue" placeholder="请输入内容" count ></u--textarea></view>
<view style="width:160upx;text-align: center;padding-top: 10px;line-height: 80upx;">
<view style="padding: 20upx;padding-top: 40px;"><u-button @click="submitReply()" type="primary" text="发布"></u-button></view>
<view style="padding: 60upx 30upx;">
<view><u--textarea confirmType="done" style="border: none;background: #F4F4F4;" :height="50" v-model="inputValue" :placeholder="'回复 '+this.replyInfo.replyName" count ></u--textarea></view>
<view style="width:160upx;padding-top: 10px;line-height: 80upx;float: right;">
<view style="padding: 20upx;margin-top: 20upx;"><u-button style="padding: 2upx 30upx;height: 52upx;background: #87B3FF;border-color: #87B3FF;" @click="submitReply()" type="primary" text="发布"></u-button></view>
</view>
</view>
<view>
@@ -117,6 +136,7 @@
import apiComment from '@/api/modules/comments.js'
import apiUser from '@/api/system/user.js'
import apiShares from '@/api/modules/shares.js'
import apiStat from '@/api/phase2/stat.js'
import { mapGetters } from 'vuex';
export default {
props:{
@@ -186,19 +206,33 @@
chooseUserName:'',
list:[]
},
commData:{}
commData:{},
praisesType:0,
}
},
mounted() {
this.loadData(false);
if(this.objType == 1) {
this.praisesType = 10;
}
if(this.objType == 2) {
this.praisesType = 20;
}
if(this.objType == 3) {
this.praisesType = 30;
}
},
methods: {
loadReplyMore(item){
item.showAll=!item.showAll;
},
loadData(append){ //加载数据
let params={
pageIndex:this.pageIndex,
pageSize:this.pageSize,
type:this.objType,
id:this.objId
id:this.objId,
orderField:'praises'
}
let $this=this;
uni.showLoading({
@@ -211,6 +245,7 @@
let ids=[];
let allList=[];
res.result.list.forEach(item=>{
item.showAll = false;
item.avatar='';
item.orgInfo='';
item.sex = null;
@@ -259,9 +294,12 @@
list.forEach((item,index)=>{
res.result.some(author=>{
if(author.aid==item.sysCreateAid){
if(author.avatar != '') {
if(item.parentId == "-1" ) {
item.avatar= author.avatar;
} else if(author.avatar != ''){
item.avatar=this.$config.fileUrl + author.avatar;
}
// item.avatar= author.avatar;
item.sex=author.sex;
item.orgInfo=author.orgInfo;
return true;
@@ -346,6 +384,20 @@
this.list[this.curCommentIndex].replyList.push(res.result);
this.$refs.interactToast.show({message:'发布成功',type:'success'});
this.inputShow=false;
let event = {
key: "ReplyComment",//后台的事件key 发布文章且审核通过
title: "回复评论",//事件的标题
parameters:"",//用户自定义参数 name:value,name:value
content: "每回一个评论",//事件的内容
objId: this.replyInfo.commentId,//关联的id
objType: "81",//关联的类型
objInfo: "回复评论",
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
}else{
this.$refs.interactToast.show({message:'发布失败',type:'error'});
}
@@ -426,12 +478,11 @@
},
//回复的事件
openInput(commIdx,replyIdx){
this.curCommentIndex=commIdx;
let comm=this.list[commIdx];
this.replyInfo.commentId=comm.id;
if(replyIdx){
if(replyIdx !== undefined){
this.curReplyIndex=replyIdx;
let re=comm.replyList[replyIdx];
this.replyInfo.parentId=re.id;
@@ -516,7 +567,6 @@
this.$refs.interactToast.show({message:'删除回复成功',type:'success'});
this.btnsShow=false;
}else{
console.log(res.error);
this.$refs.interactToast.show({message:'删除回复失败',type:'error'});
}
});
@@ -540,11 +590,25 @@
</script>
<style lang="scss" scoped>
.view-all-com{
// width: 304upx;
display: inline-block;
height: 52upx;
line-height: 40upx;
background: #F6F6F6;
border-radius: 26upx;
box-sizing: border-box;
padding: 4upx 40upx 4upx 40upx;
font-size: 24upx;
color: #666666;
margin-left: 100upx;
margin-top: 20upx;
}
.comment{
padding-top: 20upx;
.comment-top{
display: flex;
justify-content: space-between;
// justify-content: space-between;
line-height: 50upx;
.comment-avatar{
height: 50upx;
@@ -557,13 +621,14 @@
}
}
.comment-body{
padding: 6upx 0upx 0upx 60upx;
margin-left: 22upx;
padding: 0 0upx 0upx 60upx;
color: #373737;
.comment-content{
word-break:break-all;
padding: 0upx 10upx 10upx 0upx;
font-size: 28upx;
color: #333333;
color: #666666;
}
.comment-btns{
display: flex;

View File

@@ -9,16 +9,16 @@
<view class="content" style="padding: 10px;">
<view class="qitem" v-for="(ass,assIdx) in info.items" :key="assIdx">
<view class="qitem-info">{{assIdx+1}}.{{ass.question}}</view>
<view class="qitem-values" v-if="ass.qType==1">
<u-slider v-model="ass.answer" min="0" max="10" step="2" showValue></u-slider>
</view>
<view class="qitem-tips" v-if="ass.qType==1">
<view class="qitem-tips-start">{{ass.minText}}</view>
<view class="qitem-tips-end">{{ass.maxText}}</view>
</view>
<view class="qitem-values" v-if="ass.qType==1">
<u-slider v-model="ass.answer" min="0" max="10" step="2" showValue></u-slider>
</view>
<view v-if="ass.qType==9">
<u--textarea v-model="ass.answer" placeholder="写下您想说的话"></u--textarea>
</view>
</view>
</view>

View File

@@ -3,20 +3,24 @@
<u-toast ref="messager"></u-toast>
<view v-if="has" class="paperinfo">
<view class="paperinfo-item">
<u-cell-group>
<u-cell title="考试时长" :value="info.testDuration+'分钟'"></u-cell>
<u-cell title="及格线" :value="info.passLine"></u-cell>
<u-cell v-if="studyItemId!=''" title="考试成绩" :value="lastScore"></u-cell>
<u-cell-group :border="false">
<u-cell :border="false" icon="/static/images/icon/exam-duration.png" title="考试时长" :value="info.testDuration+'分钟'"></u-cell>
<u-cell :border="false" icon="/static/images/icon/exam-times.png" title="考试次数" :value="allowTimes"></u-cell>
<u-cell :border="false" icon="/static/images/icon/exam-score.png" title="及格线" :value="info.passLine"></u-cell>
<u-cell :border="false" v-if="studyItemId!=''" title="考试成绩" :value="lastScore"></u-cell>
<!--应该再显示最终成绩最高一次或最后一次得分-->
</u-cell-group>
</view>
<view v-if="info.info" style="padding: 40upx;color: #333333;">
{{info.info}}
</view>
<view style="padding: 20px;">
<u-button @click="startTest" type="primary" text="开始考试"></u-button>
</view>
<!--考试记录-->
<view>
<view class="endurance" v-for="(item,idx) in records" :key="idx" @click="toExamDetail(item)">
<view class="exam">提交时间{{item.lastTime}}</view>
<view class="exam-time">提交时间{{item.lastTime}}</view>
<view class="endurance-cen">
<view>
<view style="display: flex;margin-top: 9px;">
@@ -28,6 +32,9 @@
<view class="patientlys" style="">{{item.testDuration}}</view>
</view>
</view>
<view>
<view class="endurance-btn"><text>查看试卷</text> </view>
</view>
</view>
</view>
</view>
@@ -70,6 +77,7 @@
show:0,
toLetter:numberToLetter,
testType:getQuestionType,
allowTimes:'无限制',
has:true,
startTime:null,
testStart: false,
@@ -83,6 +91,7 @@
},
mounted() {
this.loadExamInfo();
this.loadRecord();
},
watch:{
studyId(newVal){
@@ -93,8 +102,10 @@
loadExamInfo(){
apiCourse.getExam(this.content.id).then(res=>{
if(res.status==200){
this.info=res.result;
if(res.result.times>0){
this.allowTimes=res.result.times;
}
this.info=res.result;
}else if(res.status==404){
//没有找到考试信息
}else{
@@ -163,12 +174,13 @@
}
.endurance{
height: 90px;
background: #FFFFFF;
background: #F9F9F9;
margin-top: 10px;
padding-bottom: 10px;
.exam{
.exam-time{
font-size: 15px;
color: #5EB6A4;
font-weight: Medium;
color: #333333;
padding-top: 15px;
margin-left: 15px;
}
@@ -177,7 +189,14 @@
display: flex;
justify-content: space-between;
margin-right: 11px;
.endurance-btn{
margin-top: 40upx;
background-color: #EAF1FF;
padding: 8upx 20upx;
color:#387DF7;
border-radius: 6upx;
font-size: 28upx;
}
.schedule{
font-size: 14px;
color: #868686;

View File

@@ -13,41 +13,43 @@
<view v-if="info.file && info.file!=''" class="homework-info">
<view class="homework-label">作业附件</view>
<view class="homework-value">
<a :href="fileBaseUrl+info.file" target="_blank">下载作业附件</a>
<a :href="fileBaseUrl+info.file" target="_blank" style="color: #387DF7;">下载作业附件</a>
</view>
</view>
<view class="homework-info">
<view class="homework-label">截止时间</view>
<view class="homework-value" :style="{color:close? 'red':''}">{{info.deadTime? info.deadTime: '无'}}</view>
</view>
<view>
<!-- <view>
<u-divider text="填写作业内容并提交"></u-divider>
</view>
<view class="homework-info" style="margin-right: 43rpx; ">
</view> -->
<view class="homework-info" v-if="info.submitMode!=2">
<view class="homework-label">上传附件</view>
<view class="homework-value">
<view >
<u--textarea :height="200" v-model="answer" placeholder="在此输入内容"></u--textarea>
</view>
<view style="padding-top:10px;">
<u-upload uploadIcon="plus" :fileList="fileList" @afterRead="afterRead" @delete="deleteFile" name="hwfile" :maxCount="1">
</u-upload>
</view>
<u-upload uploadIcon="plus" :fileList="fileList" @afterRead="afterRead" @delete="deleteFile" name="hwfile" :maxCount="1">
</u-upload>
</view>
</view>
<view class="homework-info" v-if="info.submitMode!=1">
<view class="homework-label">作业内容</view>
<view class="homework-value">
<u--textarea :height="200" v-model="answer" placeholder="在此输入内容"></u--textarea>
</view>
</view>
<view class="homework-btn">
<u-button type="primary" @click="submitHomework()" :text="records.length>0?'重新提交':'提交'"></u-button>
</view>
</view>
<!--作业提交记录-->
<view class="hwlist content" v-if="records.length>0">
<view v-for="record in records" :key="record.id">
<view style="display: flex;justify-content: space-between;">
<view style="color: #6b6b6b; ">已提交作业</view>
<view>{{record.endTime}}</view>
<view class="hwlist-row" v-for="record in records" :key="record.id">
<view class="hwlist-info-title">
<view>已提交作业</view>
<view class="hwlist-info-time">{{record.endTime}}</view>
</view>
<view>
<view style="padding: 20upx;">{{record.hwAnswer}}</view>
<view style="padding: 20upx 0upx;">{{record.hwAnswer}}</view>
<view v-if="record.filePath!=''">
<a :href="fileBaseUrl+record.filePath" target="_blank">作业附件</a>
</view>
@@ -91,7 +93,12 @@
},
watch:{
studyId(newVal){
this.loadRecord();
this.loadHomeworkInfo();
},
content(newVal,oldVal){
if(newVal.id!=oldVal.id){
this.loadHomeworkInfo();
}
}
},
methods: {
@@ -127,39 +134,38 @@
contentId:this.content.id
}
apiCourseStudy.myHomeworkList(params).then(rs=>{
if(rs.status==200){
this.records=rs.result;
if(rs.status==200 && rs.result){
this.records=rs.result;
}
})
},
submitHomework() {//提交作业
let oldTime=new Date(this.info.deadTime).getTime()
let newTime=+new Date()
if(oldTime<newTime){
return this.$refs.messager.show({message:'提交作业时间已过期,无法提交',type:'error'})
}
let oldTime=new Date(this.info.deadTime).getTime()
let newTime=+new Date()
if(oldTime<newTime){
return this.$refs.messager.show({message:'提交作业时间已过期,无法提交',type:'error'})
}
// if(newTime<oldTime){
// return this.$refs.messager.show({message:'',type:'error'})
// }
if(this.content.submitMode==1){
if(this.filePath==''){
this.$refs.messager.show({message:'请上传作业内容',type:'error'})
return;
}
}else if(this.content.submitMode==2){
if(this.answer==''){
this.$refs.messager.show({message:'请先填写作业内容',type:'error'})
return;
}
}else{
if(this.answer=='' && this.filePath==''){
this.$refs.messager.show({message:'请填写或上传作业',type:'error'})
return;
}
}
if(this.content.submitMode==1){
if(this.filePath==''){
this.$refs.messager.show({message:'请上传作业内容',type:'error'})
return;
}
}else if(this.content.submitMode==2){
if(this.answer==''){
this.$refs.messager.show({message:'请先填写作业内容',type:'error'})
return;
}
}else{
if(this.answer=='' && this.filePath==''){
this.$refs.messager.show({message:'请填写或上传作业',type:'error'})
return;
}
}
let pamars = {
studyItemId: this.studyItemId,//学习内容记录id,
studyId: this.studyId,//学习id,
courseId: this.content.courseId,//课程id,
contentId: this.content.id,//内容id,
@@ -170,13 +176,17 @@
hwAnswer: this.answer,//文本提交的信息
score: 0
}
if(this.studyItemId){
pamars.studyItemId=this.studyItemId;//学习内容记录id,
}
apiCourseStudy.saveHomework(pamars).then(res=>{
if(res.status==200){
this.$refs.messager.show({message:'作业已提交',type:'success'})
//this.$refs.messager.show({message:'作业已提交',type:'success'})
uni.showToast({title:'提交成功',type:'success'})
this.filePath='';
this.fileList=[];
this.answer='';
this.records=[];
this.records.push(res.result);
this.records=[res.result];
this.$emit("submit", this.content);
}else {
this.$message.error(res.message);
@@ -186,7 +196,7 @@
},
//删除文件
deleteFile(event) {
this[`fileList${event.name}`].splice(event.index, 1)
this.fileList.splice(event.index, 1)
},
//上传附件
async afterRead(event) {
@@ -208,41 +218,47 @@
<style lang="scss" scoped>
.homework {
padding-bottom: 10px;
padding: 0upx 20upx 20upx 20upx;
background-color: #fff;
.homework-info {
margin-right: 30upx;
border-bottom: 1px solid rgba(153,153,153,0.1);
.homework-label {
padding: 60rpx 43px 10rpx 40rpx;
padding-top: 10upx;
font-weight: 650;
font-size: 32rpx;
font-size: 32upx;
color: #444;
}
.homework-value {
padding-left: 70rpx;
padding: 32upx 0upx;
font-weight: 400;
font-size: 28rpx;
font-size: 28upx;
color: #787878;
word-break:break-all;
// background-color: #FFFFFF;
/deep/ .u-upload__button{
background: #fff;
}
// /deep/ textarea{
// //background: #F5F5F5;
// }
}
}
}
.u-textarea{
background-color: #F5F5F5;
}
.hwlist {
margin-bottom: 30px;
.hwlist-row {
display: flex;
line-height: 60upx;
border-bottom: 1px solid #d2d2d2;
.hwlist-time {
a{
text-decoration: none;
}
.hwlist-info-title {
display: flex;
justify-content: space-between;
color: #6b6b6b;
}
.hwlist-info-time {
color: #6c6c6c;
}

View File

@@ -1,16 +1,16 @@
<template>
<!--用于显示课程的图片-->
<view class="img-box" id="img-box">
<image style="background-color: #eeeeee;"
<image style="background-color: #eeeeee"
:class="{'border':border}"
:style="`width:${width};height:${height};`"
mode="aspectFit "
:src="imageUrl"
@error="imageError"></image>
<text v-if="textShow && isTextShow == 1" class="text mid" style="color: #fff !important;" v-html="name"></text>
<!-- <text v-if="textShow && isTextShow == 1" class="text mid" style="color: #fff !important;" v-html="name"></text>
<text v-if="textShow && isTextShow ==2" class="text mini" style="color: #fff !important;" v-html="name"></text>
<text v-if="textShow && isTextShow ==3" class="text max" style="color: #fff !important;" v-html="name"></text>
<!-- <text v-if="textShow && isTextShow ==4" class="text end" style="color: #fff !important;" v-html="name"></text> -->
<text v-if="textShow && isTextShow ==3" class="text max" style="color: #fff !important;" v-html="name"></text> -->
<!-- <text class="text" style="color: #fff !important;" v-html="name"></text> -->
</view>
</template>
@@ -44,7 +44,7 @@
name = this.course.courseName.replace('color:#ff0000','color:#fff');
}
if(this.course && this.course.title && this.course.title !== '') {
name = this.course.title.replace('color:#ff0000','color:#fff');
name = this.course.title.replace('color:#ff0000','color:#fff');
}
return name;
// course.name || course.courseName || course.title
@@ -67,7 +67,7 @@
return this.$config.fileUrl+this.course.courseImage;
}else if(this.course.coverImg == '' || this.course.courseImage == '' || this.course.image == ''){
this.textShow = true;
return '/static/images/course/courseDefault.png'
return this.$config.context+'/static/images/course/courseDefault.png'
}
}
@@ -118,31 +118,35 @@
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
font-size: 1em;
top: 36%;
left: 7%;
-webkit-line-clamp: 2;
}
.mid{
font-size: 16upx;
top: 36%;
left: 7%;
-webkit-line-clamp: 1;
}
.mini{
font-size: 12upx;
top: 36%;
left: 7%;
-webkit-line-clamp: 2;
}
.max{
font-size: 38upx;
top: 36%;
left: 7%;
-webkit-line-clamp: 3;
}
.end{
font-size: 12upx;
top: 36%;
left: 7%;
-webkit-line-clamp: 2;
}
// .mid{
// font-size: 3em;
// top: 36%;
// left: 7%;
// -webkit-line-clamp: 1;
// }
// .mini{
// font-size: 3em;
// top: 36%;
// left: 7%;
// -webkit-line-clamp: 2;
// }
// .max{
// font-size: 3em;
// top: 36%;
// left: 7%;
// -webkit-line-clamp: 3;
// }
// .end{
// font-size: 3em;
// top: 36%;
// left: 7%;
// -webkit-line-clamp: 2;
// }
}
</style>

View File

@@ -0,0 +1,154 @@
<template>
<view class="course-re-list">
<view class="course-re-index" v-for="course in items" :key="course.id" @click="toCourseDetail(course)">
<view class="course-img">
<text class="img-score">
<image style="width:28upx;height:28upx;margin-right: 6upx;" src="../../static/images/icon/index-start.png" mode=""></image>
{{converToScore(course.score)}}</text>
<course-image :course="course" width="332upx" height="192upx"></course-image>
<!-- <image style="width: 100%;height:100%;border-radius: 16upx;" src="../../static/images/course.png" mode=""></image> -->
</view>
<view class="course-title">
{{course.name}}
</view>
<view class="course-text">
<text style="margin-right: 6upx;" v-if="course.teacher">{{course.teacher}} |</text> {{formatUserNumber(course.studys || course.studies)}}人已学
</view>
<view class="course-type">
<text class="type-index" v-if="sysTypeName(course.sysType1) != ''">{{sysTypeName(course.sysType1)}}</text>
<text class="type-tow" v-if="sysTypeName(course.sysType2) != ''">{{sysTypeName(course.sysType2)}}</text>
</view>
</view>
</view>
</template>
<script>
import { mapGetters,mapActions} from 'vuex';
import {toScore,formatUserNumber} from '@/utils/tools.js'
export default {
props:{
items:{
type:Array,
},
},
computed: {
...mapGetters(['userInfo','sysTypeMap'])
},
data() {
return {
converToScore:toScore,
formatUserNumber,
}
},
methods: {
sysTypeName(code){
if(code=='' || code==0){return '';}
return this.sysTypeMap.get(code);
},
//课程跳转详情
toCourseDetail(citem) {
if(citem.source == 1){
uni.navigateTo({
url: '/pages/study/studydetail?id='+citem.id+'&type='+citem.type
});
} else {
uni.navigateTo({
url: '/pages/study/courseStudy?id=' + citem.id
});
// if (citem.type == 10) {
// uni.navigateTo({
// url: '/pages/resource/microDetail?id=' + citem.id
// });
// } else if (citem.type == 20) {
// uni.navigateTo({
// url: '/pages/resource/courseDetail?id=' +citem.id
// });
// }
}
},
}
}
</script>
<style scoped lang="scss">
.course-re-list{
display: flex;
flex-wrap: wrap;
// margin-top: 20upx;
.course-re-index{
padding: 15upx 0;
width: 335upx;
min-width: 335upx;
&:nth-child(2n-1){
margin-right: 20upx;
}
.course-img{
width: 335upx;
height: 188upx;
// line-height: 0;
border-radius: 16upx;
position: relative;
/deep/ uni-image {
border-radius: 8upx;
}
.img-score{
// display: inline-block;
padding: 7upx 15upx;
box-sizing: border-box;
position: absolute;
right:2upx;
bottom: -4upx;
color: #FFFFFF;
font-size: 28upx;
z-index: 99;
// width: 136upx;
height: 44upx;
background: #1767FF;
// background: ;
// background: rgba($color: #1767FF, $alpha: 0.2);
border-radius: 24upx 0px 8upx 0px;
backdrop-filter: blur(20px);
}
}
.course-title{
margin-top: 20upx;
font-size: 28upx;
color: #39424C;
display: -webkit-box;
word-break:break-all;
// white-space:pre-wrap;
overflow: hidden;
// text-overflow:ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
box-sizing: border-box;
}
.course-text{
margin-top: 20upx;
font-size: 28upx;
color: #666666;
}
.course-type{
margin-top: 20upx;
.type-index{
font-size: 22upx;
color: #528CEC;
background: rgba($color: #387DF7, $alpha: 0.1);
border-radius: 16upx;
margin-right: 12upx;
padding: 2upx 12upx;
}
.type-tow{
font-size: 22upx;
color: #D98135;
background: rgba($color: #FF7900, $alpha: 0.1);
border-radius: 16upx;
margin-right: 12upx;
padding: 4upx 12upx;
}
}
}
}
</style>

View File

@@ -1,12 +1,17 @@
<template>
<view>
<view @click="showFilter()" style="line-height: 34upx;height: 35upx;padding-right: 20upx;font-size: 32upx;">
<text style="color: #666;font-size: 30rpx;">筛选</text>
<image src="../../static/images/filter.png" style="width: 38upx;height: 38upx;vertical-align: middle;"></image>
<view style="line-height: 34upx;height: 35upx;padding-right: 40upx;font-size: 32upx;">
<!-- <text style="color: #666;font-size: 30rpx;">筛选</text> -->
<image @click="showFilter()" src="../../static/images/filter.png" style="width: 36upx;height: 36upx;vertical-align: middle;"></image>
<text v-if="clearswitch" class="clearsift" @click="clearsf()">清除筛选</text>
</view>
<u-popup :show="filterShow" mode="right" @close="closeFilter" :safeAreaInsetTop="true" :closeable="true">
<view :style="`width: ${filterWidth};padding-top: 5px;`" style="height: 100vh; overflow: auto;">
<view v-if="type==1" >
<!-- ${filterWidth} -->
<u-popup :show="filterShow" mode="center" @close="closeFilter" :safeAreaInsetTop="true" :closeable="false">
<view :style="{width:filterWidth}" style="height: 100vh;padding-top: 32upx; overflow: auto;position: relative;">
<view v-if="type==1" style="margin-bottom: 400upx;">
<view class="filter-title-top">
<u-icon @click="filterShow = false" class="icon" name="arrow-left" color="#333333" size="20"></u-icon>课程分类
</view>
<view class="filter-item">
<view v-if="noOrder" class="filter-title">排序</view>
<view v-if="noOrder" class="filter-body">
@@ -15,28 +20,31 @@
</view>
<view class="filter-title">授课方式</view>
<view class="filter-body">
<!-- <view class="filter-option" :class="{'filter-checked':course.courseType==10}" @click="setCourseFilter('courseType',10)">微课</view> -->
<view class="filter-option" :class="{'filter-checked':course.courseType==20}" @click="setCourseFilter('courseType',20)">录播课</view>
<view class="filter-option" :class="{'filter-checked':course.courseType==30}" @click="setCourseFilter('courseType',30)">线下课</view>
<view class="filter-option" :class="{'filter-checked':course.courseType==40}" @click="setCourseFilter('courseType',40)">学习项目</view>
</view>
<!-- <view class="filter-title">应用场景</view>
<view class="filter-body">
<view class="filter-option"
v-for="scence in courseScenceList"
:key="scence.id"
:class="{'filter-checked':checkScence(scence)}"
@click="setCourseFilter('scence',scence)">{{scence.name}}</view>
</view> -->
<view class="filter-title">内容分类</view>
<view class="">
</view>
<view class="filter-title" style="margin-top: 10upx;">内容分类</view>
<view class="filter-body">
<view class="filter-option"
v-for="sysType in courseSysTypeTree"
:key="sysType.id"
:class="{'filter-checked':course.sysType1.id==sysType.id}"
@click="setCourseFilter('sysType1',sysType)">{{sysType.name}}</view>
<!-- <view class="filter-option" @click="moreFilters('sysTypeMore',0)">更多</view> -->
<view class="filter-option" @click="toNewLink">U选小课堂</view>
<!-- <view class="filter-option" @click="toNewLink">U选小课堂</view> -->
</view>
<view class="sys-type" v-if="sysTypeTow.length > 0">
<text class="sys-type-name">{{course.sysType1.name}}</text>
<view class="sys-type-tow">
<text class="type-option" v-for="tow in sysTypeTow" :key="tow.id" :class="{'filter-checked':course.sysType2.id==tow.id}" @click="setCourseFilter('sysType2',tow)">{{tow.name}}</text>
</view>
<view class="sys-type-three">
<text class="type-option-three" v-for="three in sysTypeThree" :key="three.id" :class="{'filter-checked':course.sysType3.id==three.id}" @click="setCourseFilter('sysType3',three)">{{three.name}}</text>
</view>
</view>
</view>
</view>
@@ -69,8 +77,8 @@
</view>
</view>
<view class="filter-footer">
<view class="filter-footer-reset" @click="resetCourseFilter()"> </view>
<view class="filter-footer-submit" @click="submit()"> </view>
<!-- <view class="filter-footer-reset" @click="resetCourseFilter()"> </view> -->
<view class="filter-footer-submit" @click="submit()"> 选择好了返回课程列表页 </view>
</view>
</view>
</u-popup>
@@ -89,21 +97,28 @@
type: {
type: Number,
required:true
}
},
filterWidth:{
type:String,
default:'100%'
}
},
data(){
return{
clearswitch:false,
courseSysTypeTree:[],
courseScenceList:[],
filterShow:false,//是否显示过虑器
filterWidth:'300px',
// filterWidth:'300px',
sysTypeTow:[],
sysTypeThree:[],
course:{
orderType:-1,//表未选中,排序,最新,最热
courseType:-1,//表未选中
scenes:[],
sysType1:'',
sysType2:'',
sysType3:''
sysType1:{},
sysType2:{},
sysType3:{}
},
article:{
orderType:-1
@@ -116,8 +131,10 @@
}
},
mounted() {
this.filterWidth=(this.$width-100)+'px'; //右边出来的抽屉宽度控制
// this.filterWidth=(this.$width-100)+'px'; //右边出来的抽屉宽度控制
this.loadData();
this.clswitch();
},
computed:{
filterTags(){ //过滤标签
@@ -145,13 +162,14 @@
tags.push({type:'scenes',text:sc.name,value:sc.id})
})
}
if(filters.sysType1!=''){
if(!filters.sysType1){
tags.push({type:'sysType1',text:filters.sysType1.name,value:filters.sysType1.id})
}
if(filters.sysType2!=''){
if(!filters.sysType2){
tags.push({type:'sysType2',text:filters.sysType2.name,value:filters.sysType2.id})
}
if(filters.sysType3!=''){
if(!filters.sysType3){
tags.push({type:'sysType3',text:filters.sysType3.name,value:filters.sysType3.id})
}
}else if(this.type==2){
@@ -179,6 +197,52 @@
}
},
methods:{
clswitch(){
if(JSON.stringify(this.course.sysType1) !== '{}'){
this.clearswitch = true;
console.log(this.course,this.filterTags.length)
}else if(JSON.stringify(this.course.sysType2) !== '{}'){
this.clearswitch = true;
}else if(JSON.stringify(this.course.sysType2) !== '{}'){
this.clearswitch = true;
}else if(this.filterTags.length !== 0 && 3){
this.clearswitch = true;
}
},
// 清除筛选
clearsf(){
console.log(this.filterTags);
if(this.type==1){//生成课程查询条件
let params={
pageIndex:1,
pageSize:20,
name:'',
keyword:'',
publish:true,
device:2,
type:'',
sysType1:'',
sysType2:'',
sysType3:'',
scenes:'',
orderField:'',
orderAsc:false,
cateName:''
}
this.$emit('submit',this.filterTags,params);
this.clearswitch = false;
}
this.course.sysType1 = '';
this.course.sysType2 = '';
this.course.sysType3 = '';
this.course.orderType = -1;
this.course.courseType = -1;
this.course.scenes = [];
console.log('清除成功')
},
stopRoll(){},
toNewLink(){
location.href='https://m.qingxuetang.com/x/?appId=qxtcorp306130';
},
@@ -249,6 +313,16 @@
}else if(strType=='sysType1'){
this.course.sysType1=value;
this.sysTypeTow = value.children;
this.course.sysType2 = {};
this.course.sysType3={};
this.sysTypeThree = [];
}else if(strType=='sysType2'){
this.course.sysType2=value;
this.sysTypeThree = value.children;
this.course.sysType3={};
}else if(strType=='sysType3'){
this.course.sysType3=value;
}
},
moreFilters(){
@@ -359,65 +433,136 @@
this.$emit('submit',this.filterTags,params);
}
// console.log(this.filterTags.length,'llll')
this.clswitch();
}
}
}
</script>
<style lang="scss" scoped>
.clearsift{
font-size: 24upx;
color: #666;
margin-left: 10upx;
}
/deep/ .u-popup__content{
border-radius: 17px 0 0rpx 17px;
width: 100%;
// border-radius: 17px 0 0rpx 17px;
}
/deep/ .u-icon__icon{
top: 0px !important;
}
.filter-title-top{
height: 150upx;
line-height: 150upx;
text-align: center;
font-size: 36upx;
font-weight: 600;
color: #333333;
position: relative;
.icon{
position: absolute;
top:50upx;
left:40upx;
}
}
.filter-item{
padding: 10upx;
.filter-title{
padding: 10upx 18upx;
color: #2d2d2d;
font-size: 28rpx;
color: #333333;
font-size: 32rpx;
font-weight: bold;
}
.sys-type{
margin: 20upx;
padding: 28upx 20upx;
background: #F7F7F7;
border-radius: 8upx;
.sys-type-name{
margin-left: 12upx;
font-size: 28upx;
color: #333333;
}
.filter-checked{
color: #387DF7 !important;
}
.sys-type-tow{
margin-top: 40upx;
.type-option{
display: inline-block;
height: 60upx;
background: #FFFFFF;
border-radius: 34upx;
line-height: 60upx;
text-align: center;
color: #666666;
font-size: 28upx;
padding: 6upx 36upx;
margin-right: 28upx;
margin-bottom: 28upx;
}
}
.sys-type-three{
display: flex;
flex-wrap: wrap;
justify-content: space-around;
.type-option-three{
font-size: 28upx;
color: #666666;
}
}
}
.filter-body{
padding: 10upx 55upx;
padding: 10upx 32upx;
// text-align: center;
//display: flex;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.filter-option{
// font-weight: 620;
// background-color: #000000;
background-color: #f9f9f9;
border-radius: 45rpx;
background-color: #F7F7F7;
border-radius: 34rpx;
// border: 1px solid #cacaca;
padding: 12upx 12upx;
padding: 12upx 50upx;
display: inline-block;
height: 64rpx;
height: 60rpx;
text-align: center;
width: 190rpx;
// width: 180rpx;
font-size: 26rpx;
color: #1d1d1d;
margin: 10upx ;
color: #666666;
margin-bottom: 10upx;
margin-top: 10upx;
box-sizing: border-box;
}
.filter-checked{
background-color:#feeae9;
color: #e2331e;
margin: 10upx ;
box-sizing: border-box;
height: 64rpx;
border: 1rpx solid #e2331e;
// background-color:#feeae9;
color: #387DF7;
// margin: 10upx ;
// box-sizing: border-box;
// height: 64rpx;
// border: 1rpx solid #e2331e;
}
}
}
.filter-footer{
position: fixed;
bottom: 126upx;
left: 0;
right:0;
display: flex;
justify-content: center;
margin-top: 84upx;
padding-bottom: 30upx;
padding-top: 20upx;
.filter-footer-reset{
margin: 10upx;
border: 1px solid #FFB30F;
color: #FFB30F;
@@ -427,13 +572,16 @@
border-radius: 40upx;
}
.filter-footer-submit{
margin: 10upx;
font-size: 24rpx;
background-color:#FFB30F;
color: #FFFFFF;
padding: 20upx 80upx;
padding: 0 68upx;
// width: 236px;
height: 96upx;
line-height: 96upx;
text-align: center;
border-radius: 40upx;
background: linear-gradient(112deg, #5491FD 0%, #2A58FA 100%);
border-radius: 48upx;
font-size: 28upx;
font-weight: 600;
color: #FFFFFF;
}
}
</style>

View File

@@ -1,11 +0,0 @@
<template>
<view>
<!--内部人员分享-->
</view>
</template>
<script>
</script>
<style>
</style>

View File

@@ -2,19 +2,20 @@
<view class="interact-bar">
<view v-if="comments" class="interact-bar-item">
<image class="pto-img" src="../../static/images/icon/bar-comment.png" size="24"></image>
<text style="font-size: 15px;color: #969696;margin-left: 6upx;">{{data.comments}}</text>
<text style="font-size: 15px;color: #999999;margin-left: 8upx;">{{data.comments}}</text>
</view>
<view v-if="answers" class="interact-bar-item">
<image class="pto-img" src="../../static/images/icon/answers.png" size="24"></image>
<text style="font-size: 15px;color: #969696;margin-left: 6upx;">{{data.answers}}</text>
<image class="pto-img" src="../../static/images/icon/bar-comment.png" size="24"></image>
<text style="font-size: 15px;color: #999999;margin-left: 8upx;">{{data.answers}}</text>
</view>
<view v-if="praises" class="interact-bar-item">
<image class="pto-img" src="../../static/images/icon/bar-praise.png" size="24"></image>
<text style="font-size: 15px;color: #969696;margin-left: 6upx;">{{data.praises}}</text>
<view v-if="praises" @click="addPraise()" class="interact-bar-item">
<image v-if="isPraise" class="pto-img" src="../../static/images/icon/bar-praise-active.png" size="24"></image>
<image v-else class="pto-img" src="../../static/images/icon/bar-praise.png" size="24"></image>
<text style="font-size: 15px;color: #999999;margin-left: 8upx;">{{data.praises}}</text>
</view>
<view v-if="favorites" class="interact-bar-item">
<image class="pto-img" src="../../static/images/icon/bar-favorite.png" size="24"></image>
<text style="font-size: 15px;color: #969696;margin-left: 6upx;">{{data.favorites}}</text>
<text style="font-size: 15px;color: #999999;margin-left: 8upx;">{{data.favorites}}</text>
</view>
<!-- <view v-if="views" class="interact-bar-item">
<u-icon name="eye" color="#969696" size="18"></u-icon>
@@ -24,6 +25,10 @@
</template>
<script>
import apiStat from '@/api/phase2/stat.js'
import apiPraises from '@/api/modules/praises.js'
import apiMessage from '@/api/system/message.js'
import { mapGetters } from 'vuex';
export default {
props: {
data: {
@@ -66,17 +71,292 @@
views: {
type: Boolean,
default: true
},
type:{
type:Number,
default:0
},
pageType:{
type:Number,
default:0
},
pageParams:{
type:String,
default:''
}
},
data() {
return {
urlId:'',
loading:false,
isPraise:false,
msgPageType:0,
}
},
computed: {
watch:{
data(newVal,oldVal){
if(newVal && newVal.id!=''){
this.checkHas();
}
}
},
mounted() {
this.checkHas();
this.urlId = location.href.split('=')[1]
// this.loadUser();
if(this.pageType==0){
this.msgPageType=this.type;
}else{
this.msgPageType=this.pageType;
}
},
computed:{
...mapGetters(['userInfo']),
},
methods: {
checkHas(){
if(this.praises){
apiPraises.has(this.type,this.data.id).then(rs=>{
if(rs.status==200 && rs.result){
this.isPraise=true;
}else{
this.isPraise=false;
}
});
}
},
messageSave(refId,title,sendName,acceptName,acceptId,typeText){
// let typeText
// if(type=='share'){
// typeText='分享给我'
// }
// if(type=='favorite'){
// typeText='收藏了我发布的'
// }
// if(type=='praise'){
// typeText='点赞了我的'
// }
let content;
let conType;
if(this.type==1){
content='课程';
conType = this.data.type;
}
if(this.type==2){
content='文章'
}
if(this.type==3){
content='案例'
}
if(this.type==4){
content='提问'
}
if(this.type==5){
content='回答'
}
if(this.type==6){
content='课程笔记'
}
if(this.type==60){
content='课程笔记评论'
}
// 点赞type
if(this.type==10){
content='课程评论'
}
if(this.type==20){
content='文章评论'
}
if(this.type==30){
content='案例评论'
}
// 评论点赞通知没有关联id,评论通知暂时关闭
// if(this.type==60 || this.type==10 || this.type==20 || this.type==30 || this.type == 6) {
// return;
// content=sendName+typeText+content
// } else {
// }
if(title){
content=sendName+typeText+content+'-'+title
} else {
content=sendName+typeText+content
}
let msgPageParams=this.pageParams;
if(!msgPageParams){
//msgPageParams=this.data.id;
msgPageParams=this.urlId;
}
let message={
content,
refId,
refType:this.type,
source:1,
sendAid:this.userInfo.aid,
sendName,
acceptName,
acceptId,
title:'系统消息',
sendType:1,
conType,
source:1,
pageType:this.msgPageType,
pageParams:msgPageParams,
pageUrl:'',
sendAid:this.userInfo.aid,
}
apiMessage.save(message).then(res=>{
if(res.status!=200){ console.log('发送消息失败') }
})
},
addPraise(){
if(this.type==0){
console.log('未设置type值,1表课程,2表文章3表案例4表问答,6笔记')
return;
}
//需要判断是否已点赞,已点赞的不再加
if(!this.readonly){
let postData={
objType:this.type,
objId:this.data.id,
title:'',
}
if(this.type==1){
postData.title=this.data.name;
}else if(this.type == 5){
postData.title=this.data.content;
} else if(this.type == 10 || this.type == 20 || this.type == 30){
postData.title=this.data.content;
} else {
postData.title=this.data.title;
}
//截断处理
if(postData.title.length>50){
postData.title=postData.title.substring(0,50);
}
if(this.loading) {
return;
}
this.loading=true;
if(this.isPraise) {// 已经点赞,取消点赞
apiPraises.remove(this.type,this.data.id).then(res=>{
this.loading = false;
if(res.status==200){
if(res.result){
if(this.data.praises>0){
this.data.praises--;
}
}
this.isPraise=false;
if(this.unicom) {
this.$store.dispatch("unicomPraises",false)
}
//自己给自己点赞不算
let authorId=this.data.sysCreateAid;
if(this.type==3){ //案例取作者id
authorId=this.data.authorId;
}else if(this.type==1){ //课程取老师的id
// 目前页面上没有点赞的地方,课程有多个老师,也要给每个老师加吗?
//console.log(this.data,'点赞中课程的传的数据')
}
if(this.userInfo.aid!=authorId){
let event = {
key: "CancelPraise",//
title: "取消点赞",//事件的标题
parameters:"author:"+authorId,//用户自定义参数 name:value,name:value
content: "取消点赞"+postData.title,//事件的内容
objId: this.data.id,//关联的id
objType: this.type,//关联的类型
objInfo: this.data.title,
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
// this.$store.dispatch("userTrigger", event);
}
// this.$message({message:'取消点赞',type:'success'})
}else{
console.log('取消失败:'+res.message);
}
})
} else {
apiPraises.save(postData).then(res=>{
this.loading = false;
if(res.status==200){
if(res.result){
this.data.praises++;
}
if(this.type!=1&&this.type!=5){
this.messageSave(this.data.id,this.data.title,this.userInfo.name,this.data.sysCreateBy,this.data.sysCreateAid,'点赞了我的');
}
// if(this.type==5){
// this.messageSave(this.data.id,this.data.content,this.userInfo.name,this.data.sysCreateBy,this.data.sysCreateAid,'评论了我的');
// }
this.isPraise=true;
// this.$message({message:'点赞成功',type:'success'})
let contentText = '';
if(this.type==1){
contentText='课程';
// conType = this.data.type;
}
if(this.type==2){
contentText='文章'
}
if(this.type==3){
contentText='案例'
}
if(this.type==4){
contentText='提问'
}
if(this.type==5){
contentText='回答'
}
if(this.type==6){
contentText='课程笔记'
}
if(this.type==60){
contentText='课程笔记评论'
}
// 点赞type
if(this.type==10){
contentText='课程评论'
}
if(this.type==20){
contentText='文章评论'
}
if(this.type==30){
contentText='案例评论'
}
if(this.userInfo.aid!=this.data.sysCreateAid){
let event = {
key: "Praise",//后台的事件key 发布文章且审核通过
title: "点赞",//事件的标题
parameters:"author:"+this.data.sysCreateAid,//用户自定义参数 name:value,name:value
content: "点赞了"+contentText,//事件的内容
objId: this.data.id,//关联的id
objType: this.type,//关联的类型
objInfo: this.data.title,
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
// this.$store.dispatch("userTrigger", event);
}
}else{
console.log('点赞失败:'+res.message);
}
})
}
}
},
}
};
@@ -86,19 +366,20 @@
.interact-bar {
height: 60rpx;
display: flex;
justify-content: flex-start;
justify-content: flex-end;
.interact-bar-item {
line-height: 60rpx;
display: flex;
margin-right: 60upx;
margin-right: 30upx;
.pto-img {
margin-top: 18upx;
width: 12px;
height: 12px;
margin-right: 5upx;
margin-top: 12upx;
width: 18px;
height: 18px;
margin-left: 28upx;
// vertical-align: middle;
}
.interact-bar-icon {
margin: 0 0 0 10px;
margin: 0 0 0 10upx;
cursor: pointer;
}
}

View File

@@ -7,7 +7,7 @@
<slot>
<view class="field" @click="openInput()">
<u-icon name="edit-pen-fill" size="18" class="field-icon"></u-icon>
<text class="wenz">说点什么..</text>
<text class="wenz">写评论</text>
</view>
</slot>
</view>
@@ -15,34 +15,33 @@
<view class="interact-bar-icon"><image style="width:34upx;height: 31upx;" src="/static/images/icon/comment.png" alt=""></view>
<view class="interact-bar-txt">{{data.answers}}</view>
</view> -->
<view class="" style="display:flex;width: 50%;justify-content: flex-end;padding-right: 20rpx;">
<view class="field-right" style="display:flex;width: 50%;justify-content: flex-end;padding-right: 20rpx;margin-top: 16upx;">
<view v-if="comments" class="interact-bar-item" @click="handleComment()">
<view class="interact-bar-icon"><image style="width:40upx;height: 40upx;" src="/static/images/icon/comment.png" alt=""></view>
<view class="interact-bar-txt">{{data.comments}}</view>
<!-- <view class="interact-bar-txt">{{data.comments}}</view> -->
</view>
<view v-if="praises" @click="addPraise" class="interact-bar-item">
<view class="interact-bar-icon" v-if="isPraise"><image style="width:40upx;height: 40upx;" src="/static/images/icon/artice-praise-active.png" alt="" ></view>
<view class="interact-bar-icon" v-else><image style="width:40upx;height: 40upx;" src="/static/images/icon/artice-praise.png" alt="" ></view>
<view class="interact-bar-txt">{{data.praises}}</view>
</view>
<view v-if="shares" @click="addShare" class="interact-bar-item">
<view class="interact-bar-icon"><image style="width:40upx;height: 40upx;" src="/static/images/icon/share.png" alt=""></view>
<view class="interact-bar-txt">分享</view>
<!-- <view class="interact-bar-txt">{{data.praises}}</view> -->
</view>
<view v-if="favorites" @click="addFavorite()" class="interact-bar-item">
<view class="interact-bar-icon" v-if="isFavorite"><image style="width:40upx;height: 40upx;" src="/static/images/icon/favorite-active.png" alt="" ></view>
<view class="interact-bar-icon" v-else><image style="width:40upx;height: 40upx;" src="/static/images/icon/favorite.png" alt="" ></view>
<!-- <view class="interact-bar-txt">收藏</view> -->
<view class="interact-bar-txt">{{data.favorites}}</view>
<!-- <view class="interact-bar-txt">{{data.favorites}}</view> -->
<!-- 这里需要一个是否已经收藏的变量来控制已收藏就显示收藏数 -->
</view>
<view v-if="shares" @click="addShare" class="interact-bar-item">
<view class="interact-bar-icon"><image style="width:40upx;height: 40upx;" src="/static/images/icon/share.png" alt=""></view>
<!-- <view class="interact-bar-txt">分享</view> -->
</view>
</view>
</view>
</view>
<u-toast ref="interactToast"></u-toast>
<u-popup :show="inputShow" @close="closeInput" @open="openInput">
<u-popup :show="inputShow" @close="closeInput" @open="openInput" :round="16">
<view class="users-box" v-show="usersListShow">
<view class="users-list" v-for="u in usersList" :key="u.id" @click="userSelect(u)">
<u-avatar shape="circle" :size="50" v-if="u.avatar != ''" :src="u.avatar"></u-avatar>
@@ -56,11 +55,11 @@
</view>
<view>
<view style="display: flex;">
<view style="flex: 1;"><u--textarea :height="150" v-model="inputValue" placeholder="写下您的评论(140字以内),可以@作者哦~" count ></u--textarea></view>
<view style="width:160upx;text-align: center;padding-top: 10px;line-height: 80upx;">
<view @click="usersClick()">@</view>
<view style="padding: 20upx;"><u-button @click="submit" type="primary" text="发布"></u-button></view>
<view style="padding: 40upx 44upx 32upx 22upx;">
<view ><u--textarea style="border: none;background: #F4F4F4;" :height="50" v-model="inputValue" placeholder="写下您的评论(140字以内),可以@作者哦~" count ></u--textarea></view>
<view style="padding-top: 10px;line-height: 80upx;display: flex;float: right;">
<!-- <view @click="usersClick()">@</view> -->
<view style="padding:20upx;"><u-button @click="submit" style="padding: 2upx 30upx;height: 52upx;background: #87B3FF;border-color: #87B3FF;" type="primary" text="发布"></u-button></view>
</view>
</view>
<view>
@@ -68,21 +67,7 @@
</view>
</view>
</u-popup>
<u-popup :show="shareInfo.show" @close="closeShare" @open="addShare" mode="right">
<view style="padding: 10px 20px;line-height: 60upx;">
<view style="padding: 10upx;">请输入要分享给人的姓名</view>
<view style="padding: 10upx;">
<u--input placeholder="请输入人员姓名" border="surround" v-model="shareInfo.name"></u--input>
</view>
<view style="padding-top:20upx;">
<u-button @click="findUsers()" type="primary" text="查询"></u-button>
</view>
<view style="padding-top: 50upx;">
<!--查询内容列表-->
<view style="line-height: 60upx;" v-for="(su,suidx) in shareInfo.users" :key="suidx" @click="confirmShare(su)">{{suidx+1}}, {{su.name}} {{su.code}}</view>
</view>
</view>
</u-popup>
<interact-share ref="comShare" :data="data":type="type"></interact-share>
</view>
</template>
<script>
@@ -93,6 +78,7 @@
import apiUser from '@/api/system/user.js'
import apiCoursePortal from '@/api/modules/coursePortal.js'
import apiMessage from '@/api/system/message.js'
import apiStat from '@/api/phase2/stat.js'
import { mapGetters } from 'vuex';
export default {
props: {
@@ -143,6 +129,14 @@ export default {
type:Number,
default:0 //默认是课程
},
pageType:{
type:Number,
default:0
},
pageParams:{
type:String,
default:''
},
users:{
// type:Object,
}
@@ -206,18 +200,29 @@ export default {
if(this.type==4){
content='问答'
}
content=sendName+typeText+content+'-'+title
if(title){
content=sendName+typeText+content+'-'+title
}else{
content=sendName+typeText+content
}
let message={
content,
refId,
refType:this.type,
sendName,
acceptName,
pageType:this.type,
pageParams:refId,
acceptId,
title:'系统消息',
sendType:1,
conType,
content,
source:1,
// pageUrl:location.href,
pageUrl:'',
sendAid:this.userInfo.aid,
}
apiMessage.save(message).then(res=>{
if(res.status==200){
@@ -327,13 +332,27 @@ export default {
}
apiComment.add(cdata).then(res=>{
if(res.status==200){
this.$refs.interactToast.show({message:'发布成功',type:'success'});
// this.$refs.interactToast.show({message:'发布成功',type:'success'});
this.inputValue='';
this.data.comments++;
this.toUserDig.chooseUserId='';
this.toUserDig.chooseUserName='';
this.inputShow=false;
this.$emit("comment-success", res.result);
let event = {
key: "PublishComment",//后台的事件key 发布文章且审核通过
title: "发表评论",//事件的标题
parameters:"",//用户自定义参数 name:value,name:value
content: "每发表一个评论",//事件的内容
objId: res.result.id,//关联的id
objType: '80',//关联的类型,这里关联的类型应该是评论,不是课程
objInfo: "评论",
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
}else{
this.$refs.interactToast.show({message:'发布失败',type:'error'});
}
@@ -370,12 +389,58 @@ export default {
this.isPraise=false;
this.$refs.interactToast.show({message:'取消点赞',type:'success'});
this.$emit("praise-success", res.result);
let event = {
key: "CancelPraise",//
title: "取消点赞",//事件的标题
parameters:"author:"+authorId,//用户自定义参数 name:value,name:value
content: "取消点赞"+postData.title,//事件的内容
objId: this.data.id,//关联的id
objType: this.type,//关联的类型
objInfo: this.data.title,
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
}else{
this.$refs.interactToast.show({message:'取消失败',type:'error'});
}
})
} else {
let contentText = '';
if(this.type==1){
contentText='课程';
// conType = this.data.type;
}
if(this.type==2){
contentText='文章'
}
if(this.type==3){
contentText='案例'
}
if(this.type==4){
contentText='提问'
}
if(this.type==5){
contentText='回答'
}
if(this.type==6){
contentText='课程笔记'
}
if(this.type==60){
contentText='课程笔记评论'
}
// 点赞type
if(this.type==10){
contentText='课程评论'
}
if(this.type==20){
contentText='文章评论'
}
if(this.type==30){
contentText='案例评论'
}
apiPraises.save(postData).then(res=>{
this.loading=false;
if(res.status==200){
@@ -386,6 +451,20 @@ export default {
this.$refs.interactToast.show({message:'点赞成功',type:'success'});
this.messageSave(this.data.id,this.data.title,this.userInfo.name,this.data.sysCreateBy,this.data.sysCreateAid,'点赞了我的');
this.$emit("praise-success", res.result);
let event = {
key: "Praise",//后台的事件key 发布文章且审核通过
title: "点赞",//事件的标题
parameters:"author:"+this.data.sysCreateAid,//用户自定义参数 name:value,name:value
content: "点赞了"+contentText,//事件的内容
objId: this.data.id,//关联的id
objType: this.type,//关联的类型
objInfo: this.data.title,
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 ,//状态直接写1
source:2,
}
apiStat.sendEvent(event);
}else{
this.$refs.interactToast.show({message:'点赞失败',type:'error'});
}
@@ -454,124 +533,8 @@ export default {
},
addShare(){
//分享
this.shareInfo.show=true;
},
findUsers(){
this.shareInfo.users=[];
//模拟数据
//模拟数据
if(!this.shareInfo.name){
uni.showToast({
title: '请输入查询条件',
icon: 'none'
});
// return this.$refs.interactToast.show({message:'请输入工号或姓名',type:'warning'});
}
var name=this.shareInfo.name;
var regPos = /^\d+(\.\d+)?$/; //非负浮点数
if(regPos.test(name)){
apiUser.getByLoginName(name).then(rs=>{
if(rs.status==200){
//因为根据工号查询只会是一个人所有会有null情况而json会返回空字符串
if(rs.result!=''){
this.shareInfo.users=[rs.result];
}else{
uni.showToast({
title: '查无此用户',
icon: 'none'
});
// this.$refs.interactToast.show({message:"查无此用户",type:'warning'});
}
}else{
uni.showToast({
title: rs.message,
icon: 'none'
});
// this.$refs.interactToast.show({message:rs.message,type:'warning'});
}
})
}else{
apiUser.findByName(name).then(rs=>{
if(rs.status==200){
if(rs.result.length==0){
return uni.showToast({
title: rs.message,
icon: 'none'
});
// return this.$refs.interactToast.show({message:rs.message,type:'error'});
}
this.shareInfo.users=rs.result;
}else{
uni.showToast({
title: rs.message,
icon: 'none'
});
// this.$refs.interactToast.show({message:rs.message,type:'error'});
}
})
}
// apiUser.findByName(name).then(rs=>{
// if(rs.status==200){
// this.shareInfo.users=rs.result;
// }else{
// this.$refs.interactToast.show({message:'查询用户失败',type:'error'});
// console.log(rs.message);
// console.log(rs.error)
// }
// })
},
closeShare(){
this.shareInfo.show=false;
},
confirmShare(u){
let conType;
if(this.type == 1) {
conType = this.data.type;
}
let postData={
objType:this.type,
objId:this.data.id,
content:'',
isRead:false,
toAid:u.aid,
toAname:u.name,
conType:conType,
}
if(this.userInfo.aid==postData.toAid){
uni.showToast({
title: '不能分享给自己',
icon: 'none'
});
// return this.$message.warning("不能分享给自己")
}
apiShares.save(postData).then(rs=>{
if(rs.status==200){
if(rs.result){
this.shareInfo.show=false;
this.$refs.interactToast.show({message:'分享成功',type:'success'});
this.$emit("share-success", rs.result);
if(this.type!=3){
if(this.type==1){
this.messageSave(this.data.id,this.data.name,this.userInfo.name,u.name,u.aid,'分享给我的');
}else{
this.messageSave(this.data.id,this.data.title,this.userInfo.name,u.name,u.aid,'分享给我的');
}
}
}else{
uni.showToast({
title: '分享失败,您不能将同一资源多次分享给同一个人',
icon: 'none'
});
// this.$refs.interactToast.show({message:'分享失败,您不能将同一资源多次分享给同一个人',type:'warning'});
}
}else{
// this.$message({message:'分享失败',type:'success'});
this.$refs.interactToast.show({message:'分享处理失败',type:'error'});
console.log(rs.message);
}
});
},
this.$refs.comShare.openShare();
}
}
};
@@ -603,7 +566,7 @@ export default {
z-index: 999;
bottom: 0px;
width: 100%;
border-top: 1px solid #e8e8e8;
border-top: 1px solid rgba(153,153,153,0.12);;
height: 50px;
padding-top: 10px;
background-color: #FFFFFF;
@@ -636,15 +599,15 @@ export default {
height: 40px;
line-height: 30px;
background: rgb(247,247,249);
border-radius: 10upx;
border-radius: 34upx;
display: flex;
.field-icon{
margin-top: 2px;
margin-left: 10px;
}
.wenz{
font-size: 14px;
color: #000000;
font-size: 12px;
color: #666666;
margin-left: 2px;
margin-top: 6px;
}

View File

@@ -0,0 +1,279 @@
<template>
<view>
<u-toast ref="messager" style="z-index:100090"></u-toast>
<!--分享窗口-->
<u-popup :show="show" :closeOnClickOverlay="false" @close="closeShare" :round="14" @open="openShare" mode="bottom">
<view style="padding: 20px 20px;line-height: 60upx;">
<view style="padding: 30upx 20upx;color:#666666;text-align: center;">
<text>请输入要分享给人的姓名/工号</text>
<text @click="closeShare" style="float: right;"><image src="/static/images/close.png" style="width: 50upx;height: 50upx;"></image> </text>
</view>
<view style="padding: 10upx;">
<u-search @search="findUsers()" height="40px" bgColor="#ffffff" borderColor="rgba(153,153,153,0.3)" :showAction="false" shape="round" v-model="keyword" placeholder="姓名/工号"></u-search>
</view>
<!-- <view style="padding-top:20upx;">
<u-button @click="findUsers()" type="primary" text="查询"></u-button>
</view> -->
<view style="padding-top: 50upx;">
<view v-if="users.length>0" style="overflow-x: auto;height: 160upx;white-space: nowrap;overflow-y: hidden;">
<view style="line-height: 60upx;display: inline-block;margin: 10upx;" v-for="(su,suidx) in users" :key="suidx" @click="confirmShare(su)">
<view style="text-align: center;"><!--用户头像-->
<view v-if="su.avatar" style="border-radius: 50%;"><image :src="$config.fileUrl+su.avatar" shape="circle" style="width: 80upx;height: 80upx;border-radius: 50%;"></image></view>
<view v-else>
<image v-if="su.sex === 1 " shape="circle" src="../../static/images/man.png" style="width: 80upx;height: 80upx;" alt=""></image>
<image v-else shape="circle" src="../../static/images/woman.png" style="width: 80upx;height: 80upx;" alt=""></image>
</view>
</view>
<view style="text-align: center;font-size: 22upx;">{{su.name}}({{su.code}})</view>
</view>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import apiShares from '@/api/modules/shares.js'
import apiUser from '@/api/system/user.js'
import apiStat from '@/api/phase2/stat.js'
import apiMessage from '@/api/system/message.js'
import { mapGetters } from 'vuex';
export default {
props: {
data:{
type:Object,
default(){
return{
id:'',
type:1,
}
}
},
type:{
type:Number,
default:0 //默认是课程
},
authorId:{
type:String,
default:'' //如果不存在就使用data的创建人
},
pageType:{
type:Number,
default:0
},
pageParams:{
type:String,
default:''
}
},
computed:{
...mapGetters(['userInfo']),
},
data(){
return {
show:false,
keyword:'',
users:[],
}
},
methods:{
messageSave(refId,title,sendName,acceptName,acceptId,typeText){
let content='';
let conType;
if(this.type==1){ content='课程'; conType = this.data.type; }
if(this.type==2){ content='文章' }
if(this.type==3){ content='案例' }
if(this.type==4){ content='问答' }
content=sendName+typeText+content+'-'+title
let message={
content,
refId,
refType:this.type,
sendName,
pageType:this.type,
pageParams:this.data.id,
acceptName,
acceptId,
title:'系统消息',
sendType:1,
conType,
content,
source:1,
sendAid:this.userInfo.aid,
}
apiMessage.save(message).then(res=>{
if(res.status==200){
}
})
},
openShare(){
this.show=true;
},
findUsers(){
this.users=[];
if(!this.keyword){
//this.$refs.messager.show({message:'请输入工号或姓名',type:'warning'});
uni.showToast({ title:'请输入工号或姓名',type:'fail'})
return
}
var name=this.keyword;
var regPos = /^\d+(\.\d+)?$/; //非负浮点数
let $this=this;
if(regPos.test(name)){
apiUser.getByLoginName(name).then(rs=>{
if(rs.status==200){
//因为根据工号查询只会是一个人所有会有null情况而json会返回空字符串
if(rs.result){
$this.users=[rs.result];
$this.loadAuthorInfo($this.users,rs.result.aid);
}else{
//$this.$refs.messager.show({message:"无此用户",type:'warning'});
uni.showToast({ title:'无此用户',type:'fail'})
}
}else{
uni.showToast({ title:rs.message, icon: 'exception' });
//this.$refs.messager.show({message:rs.message,type:'warning'});
}
})
}else{
apiUser.findByName(name).then(rs=>{
if(rs.status==200){
if(rs.result.length==0){
uni.showToast({title: rs.message,icon: 'exception'});
//this.$refs.messager.show({message:rs.message,type:'error'});
}else{
let ids=[];
rs.result.forEach(item=>{
// if(item.avatar){
// item.avatar=this.$config.fileUrl + item.avatar;
// }else{
// item.sex=1;
// ids.push(item.aid);
// }
// item.avatar='';
item.sex=1;
ids.push(item.aid);
});
this.loadAuthorInfo(rs.result,ids);
this.users=rs.result;
}
}else{
uni.showToast({ title: rs.message, icon: 'exception' });
//this.$refs.messager.show({message:rs.message,type:'error'});
}
})
}
},
closeShare(){
this.show=false;
},
confirmShare(u){
if(this.type==0){
//this.$refs.messager.show({message:'未指定源类型',type:'error'});
uni.showToast({ title:'未指定源类型', icon: 'exception' });
return;
}
let conType;
if(this.type == 1) {
conType = this.data.type;
}
let postData={
objType:this.type,
objId:this.data.id,
content:'',
isRead:false,
toAid:u.aid,
toAname:u.name,
conType:conType,
}
if(this.userInfo.aid==postData.toAid){
uni.showToast({title: '不能分享给自己', icon: 'error' });
//this.$refs.messager.show({message:'不能分享给自己',type:'error',zIndex:100090});
}
let $this=this;
let authorUserId=this.data.sysCreateAid;
if(this.authorId){
authorUserId=this.authorId;
}
apiShares.save(postData).then(rs=>{
if(rs.status==200){
if(rs.result){
this.show=false;
uni.showToast({title: '分享成功', icon: 'success' });
//this.$refs.messager.show({message:'分享成功',type:'success'});
let event = {
key: "Share",//分享
title: "分享",//分享
parameters:"author:"+authorUserId,//内容的作者
source:"h5",//移动端是2
content: '分享',//事件的内容
objId: this.data.id,//关联的id
objType: this.type,//关联的类型
objInfo: this.data.title? this.data.title:this.data.name,
aid: this.userInfo.aid, //当前登录人的id
aname: this.userInfo.name,//当前人的姓名
status: 1 //状态直接写1
}
apiStat.sendEvent(event);
this.$emit("success", rs.result);
if(this.type!=3){
if(this.type==1){
//发送消息
this.messageSave(this.data.id,this.data.name,this.userInfo.name,u.name,u.aid,'分享给我的');
}else{
this.messageSave(this.data.id,this.data.title,this.userInfo.name,u.name,u.aid,'分享给我的');
}
}
}else{
uni.showToast({title: '已分享过,不能再分享', icon: 'fail' });
//this.$refs.messager.show({message:'已分享过,不能再分享',type:'warning'});
}
}else{
uni.showToast({title:rs.message, icon: 'exception' });
//this.$refs.messager.show({message:rs.message,type:'error',zIndex:100090});
}
});
},
loadAuthorInfo(list, ids) {
//加载作者信息,头像,机构信息
if (ids.length == 0) {
return;
}
apiUser.getByIds(ids).then(res => {
if (res.status == 200) {
list.forEach((item, index) => {
res.result.some(author => {
if (author.aid == item.teacherId) {
item.name= author.name;
item.orgInfo=cutOrgNamePath(author.orgInfo);
item.avatar= author.avatar;
item.code= author.code;
item.sex=author.sex;
// if(author.avatar != '') {
// item.avatar=this.$config.fileUrl + author.avatar;
// }
return true;
}else{
return false;
}
});
});
} else {
console.log('获取用户信息失败:'+res.error);
//this.$message.error(res.message);
}
});
},
}
}
</script>
<style>
</style>

View File

@@ -1,9 +1,12 @@
<template>
<view class="top">
<view v-show="showBack" class="back" @click="toBack()">
<text class="arrow"></text>
<view v-show="showBack" class="top-back" @click="toBack()">
<u-icon color="#333" size="20" name="arrow-left"></u-icon>
</view>
<view class="top-title"><slot></slot></view>
<view @click="topgae()" style="color: #387DF7;">
<slot name="right"></slot>
</view>
<view class="title"><slot></slot> </view>
</view>
</template>
@@ -17,6 +20,10 @@
showBack:{
type:Boolean,
default:false
},
goPgae:{
type:String,
default:''
}
},
data() {
@@ -25,6 +32,13 @@
}
},
methods: {
topgae() {
if(this.goPgae!=''){
uni.navigateTo({
url:this.goPgae
});
}
},
toBack(){
if(this.backUrl!=''){
if(this.backUrl == '/pages/my/index'){
@@ -57,18 +71,21 @@
<style lang="scss" scoped>
.top{
height: 40px;
// display: none;
background:linear-gradient(to bottom,#6BA0FC, #6297FD);
.back{
float: left;
color: #FFFFFF;
padding-top:8px;
background-color: #fff;
display: flex;
// justify-content: space-between;
.top-back{
color: #333;
padding-top:10px;
height: 40px;
line-height: 40px;
padding-left: 15px;
}
.title{
.top-title{
text-align: center;
font-size: 16px;
color: #F9FDFF;
font-weight: 550;
color: #333;
height: 40px;
text-align: center;
width: 80%;
@@ -78,18 +95,18 @@
line-height: 40px;
}
}
.arrow:before {
content: " ";
display: inline-block;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
height: .5rem;
width: .5rem;
border-width: 0 0 2px 2px;
border-color: #FFFFFF;
border-style: solid;
position: relative;
top: 0
}
// .arrow:before {
// content: " ";
// display: inline-block;
// -webkit-transform: rotate(45deg);
// -ms-transform: rotate(45deg);
// transform: rotate(45deg);
// height: .5rem;
// width: .5rem;
// border-width: 0 0 2px 2px;
// border-color: #FFFFFF;
// border-style: solid;
// position: relative;
// top: 0
// }
</style>

View File

@@ -0,0 +1,500 @@
<template>
<view class="recommend-index">
<view class="index-banner">
<u-swiper
:list="resonimg"
keyName="image"
@change="change"
@click="click"
></u-swiper>
</view>
<view class="course-re">
<view class="recommend-index-title" style="margin-bottom: 20upx;">
<text class="title-line"></text>
热门课程推荐
<!-- <text class="tetle-text">查看更多</text> -->
</view>
<course-list :items="courseDataList"></course-list>
</view>
<view style="margin:30upx 0 60upx 0">
<image @click="imgJup()" style="width: 100%;height:220upx" :src="fileUrl+placeholderImg.image" mode=""></image>
</view>
<view class="ranking-list">
<view class="recommend-index-title">
<text class="title-line"></text>
排行榜
</view>
<view class="list-box">
<view class="list-box-index" >
<view class="list-box-title course-bg-info">
热门课程排行榜
</view>
<view class="list-box-text" v-for="(cou,index) in courseRankingList" @click="toCourseDetail(cou)">
<image v-if="index == 0" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue01.png" mode=""></image>
<image v-if="index == 1" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue02.png" mode=""></image>
<image v-if="index == 2" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue03.png" mode=""></image>
<image v-if="index == 3" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue04.png" mode=""></image>
<image v-if="index == 4" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue05.png" mode=""></image>
<image v-if="index == 5" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue06.png" mode=""></image>
<image v-if="index == 6" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue07.png" mode=""></image>
<image v-if="index == 7" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue08.png" mode=""></image>
<image v-if="index == 8" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue09.png" mode=""></image>
<image v-if="index == 9" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue010.png" mode=""></image>
<text>{{cou.name}}</text>
</view>
</view>
<view class="list-box-index">
<view class="list-box-title art-bg-info">
热门文章排行榜
</view>
<view class="list-box-text" v-for="(arl,index) in arlRankingList" @click="toArticleDetail(arl)">
<image v-if="index == 0" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listred01.png" mode=""></image>
<image v-if="index == 1" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listred02.png" mode=""></image>
<image v-if="index == 2" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listred03.png" mode=""></image>
<image v-if="index == 3" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue04.png" mode=""></image>
<image v-if="index == 4" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue05.png" mode=""></image>
<image v-if="index == 5" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue06.png" mode=""></image>
<image v-if="index == 6" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue07.png" mode=""></image>
<image v-if="index == 7" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue08.png" mode=""></image>
<image v-if="index == 8" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue09.png" mode=""></image>
<image v-if="index == 9" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue010.png" mode=""></image>
<text>{{arl.title}}</text>
</view>
</view>
<view class="list-box-index">
<view class="list-box-title qa-bg-info">
热门问答排行榜
</view>
<view class="list-box-text" v-for="(qa,index) in qaRankingList" @click="toQaDetail(qa)">
<image v-if="index == 0" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/list-01.png" mode=""></image>
<image v-if="index == 1" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/list02.png" mode=""></image>
<image v-if="index == 2" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/list03.png" mode=""></image>
<image v-if="index == 3" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue04.png" mode=""></image>
<image v-if="index == 4" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue05.png" mode=""></image>
<image v-if="index == 5" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue06.png" mode=""></image>
<image v-if="index == 6" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue07.png" mode=""></image>
<image v-if="index == 7" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue08.png" mode=""></image>
<image v-if="index == 8" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue09.png" mode=""></image>
<image v-if="index == 9" style="width:50upx;height: 50upx;vertical-align: middle;" src="../../static/images/ranking/listblue010.png" mode=""></image>
<text>{{qa.title}}</text>
</view>
</view>
</view>
</view>
<view class="articl-recommend">
<view class="recommend-index-title">
<text class="title-line"></text>
热门文章推荐
<!-- <text class="tetle-text">查看更多</text> -->
</view>
<view class="articl-box">
<view class="articl-box-index" v-for="ar in arlDataList" @click="toArticleDetail(ar)">
<image style="width: 560upx;height: 314upx;border-radius: 24upx 24upx 0 0;" :src="fileUrl+ar.coverurl" mode=""></image>
<view class="box-index">
<view class="box-index-title" style="height:90upx">
{{ar.title}}
</view>
<view class="box-index-authr">
<author-info width="32px" height="32px" :avatar="ar.authorInfo.avatar" :name="ar.authorInfo.name" :sex="ar.authorInfo.sex"></author-info>
<!-- <image style="width: 64upx;height:64upx;vertical-align: middle;margin-right: 24upx;" src="../../static/images/woman.png" mode=""></image>
学习小助手 -->
</view>
</view>
</view>
</view>
</view>
<view class="qa-recommend">
<view class="recommend-index-title">
<text class="title-line"></text>
热门问答推荐
<!-- <text class="tetle-text">查看更多</text> -->
</view>
<view class="qa-box" style="display: flex;overflow-x: auto;">
<view class="qa-box-index" v-for="qa in qaDataList" @click="toQaDetail(qa)">
<view class="box-index-title">
{{qa.title}}
</view>
<view class="box-index-authr" style="display: flex;">
<author-info width="26px" height="26px" :avatar="qa.authorInfo.avatar" :name="qa.authorInfo.name" :sex="qa.authorInfo.sex"></author-info>
<!-- <image style="width: 64upx;height:64upx;vertical-align: middle;margin-right: 24upx;" src="../../static/images/woman.png" mode=""></image>
<text style="font-size: 28upx;color: #39424C;">学习小助手</text> -->
<text style="font-size: 28upx;color: #6E7B84;margin-top: 10upx;display: inline-block;margin-left: 20upx;">最热答案</text>
</view>
<view class="box-index-text">
{{qa.content}}
</view>
</view>
</view>
</view>
<u-divider text="没有更多了"></u-divider>
</view>
</template>
<script>
import apiIndex from '@/api/phase2/index.js';
import apiPlace from '@/api/phase2/place.js';
import { mapGetters,mapActions} from 'vuex';
import apiUser from '@/api/system/user.js';
export default {
data() {
return {
fileUrl:this.$config.fileUrl,
arlDataList:[],
qaDataList:[],
courseDataList:[],
qaRankingList:[],
arlRankingList:[],
courseRankingList:[],
resonimg:[],//轮播图
placeholderImg:{},
}
},
computed: {
...mapGetters(['userInfo'])
},
mounted(){
this.couresreso();
this.getCourseData();
// this.getSysTypeTree();
// this.findCourseData();
this.loadSysTypes();
this.getQaRanking();
this.getArtRanking();
this.getArtData();
this.getQaData();
this.getCourseRanking();
},
methods: {
imgJup() {
if(this.placeholderImg.JumpUrl){
window.open(this.placeholderImg.JumpUrl);
}
},
click(e) {
let JumpUrl = this.resonimg[e].JumpUrl;
if(JumpUrl){
window.open(JumpUrl);
}
},
change(e) {
},
couresreso() {
let key = 'mobileIndex1';
apiPlace.detail(key).then(res => {
this.resonimg = [];
if(res.result.content && res.result.content.length>10){
let lmj = JSON.parse(res.result.content)
lmj.forEach(item=>{
this.resonimg.push(
{
image: this.fileUrl+item.image,
JumpUrl: item.JumpUrl,
}
);
})
}
});
let keyImg = 'mobileIndex2';
apiPlace.detail(keyImg).then(res => {
if(res.result.content && res.result.content.length>10){
let lmj = JSON.parse(res.result.content)
this.placeholderImg = lmj[0];
}
});
},
//文章跳转详情
toArticleDetail(item) {
uni.navigateTo({
url: '/pages/resource/articeDetail?id=' + item.id
});
},
toQaDetail(item) {
uni.navigateTo({
url: '/pages/resource/qaDetail?id=' + item.id
});
},
//课程跳转详情
toCourseDetail(citem) {
if(citem.source == 1){
uni.navigateTo({
url: '/pages/study/studydetail?id='+citem.id+'&type='+citem.type
});
} else {
uni.navigateTo({
url: '/pages/study/courseStudy?id=' + citem.id
});
// if (citem.type == 10) {
// uni.navigateTo({
// url: '/pages/resource/microDetail?id=' + citem.id
// });
// } else if (citem.type == 20) {
// uni.navigateTo({
// url: '/pages/resource/courseDetail?id=' +citem.id
// });
// }
}
},
...mapActions({
// getResOwnerTree:'resOwner/getResOwnerTree',
// loadResOwners:'resOwner/loadResOwners',
getSysTypeTree:'sysType/getSysTypeTree',
loadSysTypes:'sysType/loadSysTypes'
}),
//问答排行榜
getQaRanking(){
apiIndex.qaAnswers(10).then(res=>{
if(res.status == 200) {
this.qaRankingList = res.result;
}
})
},
//文章排行榜
getArtRanking(){
apiIndex.articleViews(10).then(res=>{
if(res.status == 200){
this.arlRankingList = res.result;
}
})
},
//课程排行榜
getCourseRanking(){
apiIndex.scorelist(10,1).then(res=>{
if(res.status == 200){
this.courseRankingList = res.result;
console.log(res,'qqq')
console.log(this.courseRankingList)
}
})
},
//推荐文章
getArtData() {
apiIndex.mobieArticle(2).then(res=>{
if(res.status == 200) {
let ids = [];
res.result.forEach(item=>{
ids.push(item.sysCreateAid);
item.authorInfo={avatar:'',name:'',code:'',sex:null};
})
this.arlDataList = res.result;
this.loadAuthorInfo(res.result,ids);
}
})
},
// 推荐问答
getQaData(){
let params = {
pageSize: 4,
orderAsc: false,
orderField: 'views'
};
apiIndex.indexList(params).then(res=>{
if(res.status == 200){
let ids = [];
res.result.forEach(item=>{
ids.push(item.sysCreateAid);
item.authorInfo={avatar:'',name:'',code:'',sex:null};
})
this.qaDataList = res.result;
this.loadAuthorInfo(res.result,ids);
}
})
},
// 推荐课程
getCourseData(){
let course = {
num:6,
device: 1,
orderField: 'studys',
orderAsc: false,
topOrder: true,
};
apiIndex.mobileIndex(course).then(res=>{
if(res.status == 200) {
this.courseDataList = res.result;
}
})
},
loadAuthorInfo(list, ids) {
//加载作者信息,头像,机构信息
if (ids.length == 0) {
return;
}
const noReapetIds = [...new Set(ids)];
apiUser.getByIds(ids).then(res => {
if (res.status == 200) {
list.forEach((item, index) => {
res.result.some(author => {
if (author.aid == item.sysCreateAid) {
item.authorInfo = author;
return true;
} else {
return false;
}
});
});
} else {
console.log('加载用户信息失败:' + res.error);
}
});
},
}
}
</script>
<style scoped lang="scss">
.recommend-index{
background-color: #fff;
padding:16upx 30upx;
padding-bottom: 100upx;
.recommend-index-title{
font-size: 36upx;
font-weight: 600;
height: 40upx;
line-height: 40upx;
color: #04243C;
margin-top: 50upx;
.title-line{
display: inline-block;
width: 8upx;
height: 28upx;
background: #387DF7;
border-radius: 8upx;
margin-right: 12upx;
}
.tetle-text{
float: right;
font-size: 24upx;
color: #6E7B84;
font-weight: 400;
}
}
.ranking-list{
.list-box{
// width: 1720upx;
margin-top: 30upx;
display: flex;
overflow-x: auto;
}
.list-box-index:nth-child(1){
background: url(../../static/images/ranking/qa-box.png) no-repeat 100% / 100%;
background-position: 0 0;
}
.list-box-index:nth-child(2){
background: url(../../static/images/ranking/list-pink.png) no-repeat 100% / 100%;
background-position: 0 -1px;
}
.list-box-index:nth-child(3){
background: url(../../static/images/ranking/list-or.png) no-repeat 100% / 100%;
background-position: 0 0;
}
.list-box-index{
width: 560upx;
min-width: 560upx;
height: 880upx;
box-sizing: border-box;
border-radius: 24upx;
border: 2upx solid #E4EAEF;
padding: 34upx 30upx;
// background: url(../../static/images/ranking/qa-box.png) no-repeat 100% / 100%;
// background-position: 0 0;
margin-right: 20upx;
.list-box-title{
font-size: 32upx;
font-weight: 600;
color: #04243C;
margin-bottom: 4upx;
}
.list-box-text{
margin-top: 26upx;
font-size: 28upx;
color: #39424C;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;-webkit-line-clamp: 1;
word-break:break-all;
}
}
}
.articl-recommend{
.articl-box{
margin-top: 28upx;
display: flex;
overflow-x: auto;
.articl-box-index{
width: 560upx;
border-radius: 24upx;
border: 2upx solid #E4EAEF;
margin-right: 20upx;
.box-index{
padding: 30upx;
.box-index-title{
font-size: 32upx;
font-weight: 600;
color: #39424C;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;-webkit-line-clamp: 2;
word-break:break-all;
}
.box-index-authr{
margin-top: 30upx;
font-size: 28upx;
color: #6E7B84;
}
}
}
}
}
.qa-recommend{
.qa-box{
margin-top: 32upx;
margin-bottom: 60upx;
.qa-box-index{
background: url(../../static/images/ranking/qa-bg.png) no-repeat 100% / 100%;
background-position: 0 0;
margin-right: 20upx;
width: 560upx;
min-width: 560upx;
border: 2upx solid #E4EAEF;
border-radius: 24upx;
padding: 30upx;
box-sizing: border-box;
.box-index-title{
font-size: 32upx;
font-weight: 600;
color: #02233C;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;-webkit-line-clamp: 2;
word-break:break-all;
}
.box-index-authr{
margin-top: 30upx;
margin-bottom: 20upx;
/deep/.author-name{
color: #39424C !important;
}
}
.box-index-text{
font-size: 28upx;
color: #6E7B84;
margin-bottom: 10upx;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;-webkit-line-clamp: 2;
word-break:break-all;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,320 @@
<template>
<view>
<u-toast ref="toast"></u-toast>
<view class="news-page-btn">
<view class="btn-index" @click="selectFn">多选</view>
<view class="btn-index" :class="{'wu-list':items.length == 0}" @click="isAllClear()">清空</view>
<view class="btn-index" :class="{'wu-list':items.length == 0}" @click="allRead()">一键已读</view>
</view>
<view class="news-page-list">
<view class="list-index" v-for="item in items" :key="item.id" @click="returnRouter(item)">
<view style="margin-top: 16upx;margin-right: 20upx;">
<radio v-show="flag" @click.stop="changeChecked(item)" :checked="item.checked"/>
</view>
<view class="list-index-img">
<u-badge :isDot="!item.isRead" type="error" :absolute="true" :offset="[0,-2]"></u-badge>
<author-img :avatar="item.authorInfo.avatar" :sex="item.authorInfo.sex"></author-img>
<!-- <image style="width:80upx;height:80upx" src="../../static/images/woman.png" mode=""></image> -->
</view>
<view class="list-index-cen">
<view class="cen-name">
{{item.sendName}}
<view class="list-index-time">{{item.msgTime.split(' ')[0]}}</view>
</view>
<view class="cen-text">
{{item.content}}
</view>
</view>
</view>
<u-modal :show="modalShow" @confirm="confirm" @cancel="cancel" :showCancelButton="true" confirmText="删除" ref="uModal" :content='content'></u-modal>
<!-- <u-popup :show="flag" @close="flag = false" :overlayStyle="{background: 'rgba(245, 245, 245, 0.1)'}" :closeOnClickOverlay="true">
<view class="information_bottom">
<view class="del" @click="delfirm()">删除</view>
<view class="qux" @click="flag = false">取消</view>
</view>
</u-popup> -->
<view class="information_bottom" v-show="flag">
<view class="del" @click="delfirm()">删除</view>
<view class="qux" @click="flag = false">取消</view>
</view>
</view>
</view>
</template>
<script>
import apiMessage from '@/api/system/message.js';
export default {
props:{
items:{
type:Array,
default:()=>[]
}
},
data() {
return {
isAll:0,//0所有 1选择
content:'确认删所选信息吗?',
modalShow:false,
flag: false, //控制勾选按钮的显示
}
},
methods: {
returnRouter(item) {
if(!item.isRead){
apiMessage.updateIsRead([item.id]).then(res=>{
if(res.status == 200) {
item.isRead = !item.isRead;
}
})
}
if(item.pageType) {
if (item.pageType == 2 || item.pageType == 20) {
uni.navigateTo({
url: '/pages/resource/articeDetail?id=' + item.pageParams
});
} else if (item.pageType == 4 || item.pageType == 40) {
uni.navigateTo({
url: '/pages/resource/qaDetail?id=' + item.pageParams
});
} else {
uni.navigateTo({
url: '/pages/study/courseStudy?id=' + item.pageParams
});
}
} else {
if (item.refType == 2) {
uni.navigateTo({
url: '/pages/resource/articeDetail?id=' + item.refId
});
} else if (item.refType == 4) {
uni.navigateTo({
url: '/pages/resource/qaDetail?id=' + item.refId
});
} else {
uni.navigateTo({
url: '/pages/study/courseStudy?id=' + item.refId
});
}
}
},
cancel() {
this.modalShow = false;
},
delfirm() {
this.isAll = 1;
this.modalShow = true;
this.content ='确认删所选信息吗?';
},
confirm() {
if(this.isAll == 0) {
this.allClear();
} else{
this.delList();
}
},
//改变checked的值
changeChecked(val){
val.checked=!val.checked
},
//控制勾选等操作是否显示
selectFn() {
if(this.items.length!=0&&!this.flag){
this.flag = true;
}
},
delList() {
let ids=[];
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].checked) {
ids.push(this.items[i].id);
}
}
if(ids.length==0){
return this.$refs.toast.show({ message: '请先进行勾选', type: 'error' });
}
apiMessage.del(ids).then(res => {
if (res.status == 200) {
this.$refs.toast.show({ message: '删除成功', type: 'success' });
// this.queryMessage(true);
this.flag = false;
this.modalShow = false;
this.$emit('loadMessage');
} else {
this.$refs.toast.show({ message: '删除失败', type: 'error' });
}
});
},
isAllClear() {
if(this.items.length == 0) {
return
}
this.isAll = 0;
this.modalShow = true;
this.content='确认删所有信息吗?'
},
allClear() {
apiMessage.cleanAll().then(res=>{
if(res.status == 200) {
this.modalShow = false;
this.$emit('loadMessage');
}
})
},
allRead(){
this.flag = false;
if(this.items.length == 0) {
return
}
let ids = this.items.map(item=>{
if(!item.isRead) {
return item.id;
}
})
apiMessage.readAll().then(res=>{
if(res.status == 200) {
this.$emit('loadMessage');
}
})
}
}
}
</script>
<style scoped lang="scss">
.wu-list{
background-color: #eee;
}
/deep/ .u-modal{
width: 288px !important;
border-radius: 28upx;
}
/deep/ .u-modal__content{
text-align: center;
font-size: 36upx;
font-weight: 600;
color: #333333;
padding: 33px 25px 33px 25px;
}
/deep/ .uni-radio-input{
width: 18px !important;
height: 18px !important;
background-color: #fff !important;
border: 4upx solid #8A91A4 !important;
}
/deep/ .uni-radio-input-checked{
border: 4upx solid #007DFF !important;
}
/deep/ uni-radio .uni-radio-input.uni-radio-input-checked:before {
// font: normal normal normal 28px/1 uni;
content: "·";
color: #007DFF;
font-size: 120px;
position: absolute;
top: -35%;
left: 50%;
transform: translate(-50%,-48%) scale(.73);
-webkit-transform: translate(-50%,-48%) scale(.73);
}
.news-page-btn{
height: 80upx;
padding: 30upx 32upx 0 36upx;
.btn-index{
font-size: 28upx;
color: #666666;
float: right;
margin-left: 20upx;
padding: 6upx 32upx 6upx 28upx;
border: 2upx solid rgba(153,153,153,0.2);
border-radius: 26upx;
}
.btn-index:first-child{
margin-left: 0;
float: left;
}
}
.news-page-list{
padding: 0 32upx 0 36upx;
box-sizing: border-box;
.list-index{
display: flex;
padding: 40upx 0;
border-bottom: 2upx solid rgba(153,153,153,0.1);;
.list-index-img{
width: 80upx;
position: relative;
}
.list-index-cen{
margin-left: 30upx;
width: 100%;
.cen-name{
font-size: 28upx;
font-weight: 500;
color: #333333;
margin-top: 4upx;
}
.cen-text{
font-size: 24upx;
color: #999999;
margin-top: 4upx;
word-break:break-all;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;-webkit-line-clamp: 1;
}
}
.list-index-time{
float: right;
margin-top: 4upx;
// width: 300upx;
font-size: 24upx;
color: #999999;
}
}
}
.information_bottom {
width: 100%;
// height: 120upx;
background: #ffffff;
position: fixed;
left: 0;
bottom: 50px;
box-shadow: 0px -1px 6px 0px rgba(83,83,83,0.18);
// display: flex;
.qux {
// width: 316upx;
height: 76upx;
// border: 1px solid #dcdcdc;
// margin-left: 42upx;
// margin-top: 25upx;
// border-radius: 40upx;
font-size: 28upx;
color: #999999;
text-align: center;
line-height: 76upx;
}
.del {
// width: 316upx;
height: 76upx;
// background: #6194fe;
// margin-left: 42upx;
// margin-top: 25upx;
// border-radius: 40upx;
font-size: 28upx;
color: #F75B53;
text-align: center;
line-height: 76upx;
border-bottom: 1upx solid #eee;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

View File

@@ -1,62 +1,128 @@
<template>
<video id="myVideo" style="width: 100%;"
:src="fileBaseUrl+coursewareInfo.content.content"
@error="videoErrorCallback"
:initial-time="videoPlayingTime"
@play="onPlayerPlay"
@pause="onPlayerPause"
@ended="onPlayerEnded"
@timeupdate="onPlayerPlaying"
@fullscreenchange="onFullScreen"
controls>
<view class='process-container'>
<view class="video-controls-play">
<image :src="palyFlag ? '../../static/img/start.png' : '../../static/img/pause.png'" class='video-controls-icon' @click='videoOpreation'/>
<view id="xvideoPlayer-box" class="video-box">
<video id="xvideoPlayer" style="width: 100%;"
:src="url"
:controls="false"
:enable-play-gesture="false"
:initial-time="initPlayingTime"
@error="error"
@touchend="onTouchend"
@play="onPlay"
@pause="onPause"
@ended="onEnded"
@timeupdate="onTimeUpdate"
@fullscreenchange="onFullScreen"
@loadeddata="onLoad"
@loadedmetadata="onMetaLoad"
@controlstoggle="onControlsToggle"
></video>
<view id="xplayer-control" >
<view class="process-container" v-if="contrlShow">
<view class="controller-play">
<image :src="require(playing? './images/pause.png':'./images/play.png')" @click.stop='videoOpreation'/>
</view>
<view class="currtime">{{currtime}}</view>
<view class='slider-container'>
<slider :disabled="!drag" @change.stop="sliderChange" @changing="sliderChanging" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="12"/>
</view>
<view class="druationTime">{{druationTime}}</view>
<view class="druationTime">
<view id="myVideoSpeed" class="player-speed btn-speed">
<view @click="showSpeedCtrl">{{videoSpeed === 1 ? '倍速' : `${videoSpeed}x`}}</view>
<view class="speed-control" v-if="speedListShow">
<view class="speed-control-list">
<view class="li"
v-for="item in speedList"
:key="item"
@click="changeSpeed(item)"
:data-value="item"
:class="{'current': videoSpeed === Number(item)}">
{{ item }}x
</view>
</view>
</view>
</view>
</view>
<view class="controller-screen">
<image :src="require(fullScreenFlag? './images/back.png':'./images/full.png')" @click.stop='fullScreen'/>
</view>
</view>
<view class="currtime">{{currtime}}</view>
<view class='slider-container'>
<slider @change="sliderChange" @changing="sliderChanging" step="1" :value="sliderValue" backgroundColor="#9f9587" activeColor="#d6d2cc" block-color="#FFFFFF" block-size="16rpx"/>
</view>
<view class="druationTime">{{druationTime}}</view>
<image :src="fullScreenFlag ? '../../static/img/videoBack.png' : '../../static/img/fullScreen.png'" class='video-controls-icon' @click='videoAllscreen'></image>
</view>
</video>
</view>
</template>
<script>
import {mapGetters} from 'vuex'
import studyUtil from '@/utils/study.js';
export default {
props: {
url:{
type: String,
require: true
},
initTime:{//默认播放的位置,第几秒
watermark:{
type: Boolean,
default: true
},
name:{
type: String,
default: ''
},
drag:{
type: Boolean,
default: true
},
inittime:{//默认播放的位置,第几秒
type: Number,
default: 0
},
},
data() {
return {
fullScreenFlag: false,
currtime:'00:00:00',//当前播放时间 字符串 计算后
druationTime:'00:00:00',//总时间 字符串 计算后
bool:false,
contrlShow:false,//是否显示控制条
contrlShowTimeout:null,//显示控制条句柄
videoContext:null,//播放器
fullScreenFlag: false,//是否全屏
currtime:'00:00',//当前播放时间 字符串 计算后
druationTime:'00:00',//总时间 字符串 计算后
initPlayingTime:0,//指定播放的时间位置
sliderValue: 0, //控制进度条slider的值
updateState: false, //防止视频播放过程中导致的拖拽失效
palyFlag:false,
updateState: true, //防止视频播放过程中导致的拖拽失效
playing:false,//是否在播放中
curVideo:{
duration:0
},
touchNum:0,
speedListShow:false,
speedList:["2.0", "1.5", "1.25", "1.0", "0.75", "0.5"],
videoSpeed: 1.0, // 当前倍速:
};
},
computed: {
...mapGetters(['userInfo']),
},
watch:{
url(newVal,oldVal){
this.videoContext.stop();
this.playing=false;
},
inittime(newVal,oldVal){
this.initPlayingTime=newVal;
}
},
mounted() {
this.initPlayingTime=this.inittime;
this.videoContext=uni.createVideoContext("xvideoPlayer", this);
},
methods: {
// video_back: function (e) {
// this.fullScreenFlag ? this.videoContext.requestFullScreen() : this.videoContext.exitFullScreen();
// // this.fullScreenFlag ? this.bool=false : this.bool=true;
// this.fullScreenFlag= !this.fullScreenFlag;
// },
// 全屏+退出全屏
videoAllscreen(e) {
this.fullScreenFlag ? this.videoContext.exitFullScreen() : this.videoContext.requestFullScreen();
// this.fullScreenFlag ? this.bool=true : this.bool=false;
this.fullScreenFlag=!this.fullScreenFlag;
fullScreen(){
if(this.fullScreenFlag){
this.videoContext.exitFullScreen();
this.fullScreenFlag=false;
}else{
this.videoContext.requestFullScreen();
this.fullScreenFlag=true;
}
},
// 根据秒获取时间
formatSeconds(a) {
@@ -73,14 +139,29 @@
return "00:00";
}
},
changeSpeed(e) {
// 获取选择的倍速
let value = e;
this.videoSpeed = Number(value);
this.videoContext.playbackRate(this.videoSpeed);
studyUtil.setVideoSpeed(this.videoSpeed);
this.speedListShow=false;
},
showSpeedCtrl(){
if(this.speedListShow){
this.speedListShow=false;
}else{
this.speedListShow=true;
}
},
//开始+暂停
videoOpreation() {
this.palyFlag ? this.videoContext.play() : this.videoContext.pause();
this.palyFlag= !this.palyFlag;
this.playing ? this.videoContext.pause() : this.videoContext.play();
this.playing= !this.playing;
},
// 播放进度变化时触发event.detail = {currentTime, duration} 。触发频率 250ms 一次
videoUpdate(e) {
let duration=this.live.liveRoomRecordList[0].duration;
let duration=this.curVideo.duration;
let sliderValue = e.detail.currentTime / duration * 100;
let second=sliderValue / 100 * duration;
if (this.updateState) { //判断拖拽完成后才触发更新,避免拖拽失效
@@ -88,8 +169,9 @@
}else{
}
this.druationTime = this.formatSeconds(duration);
this.currtime = this.formatSeconds(second);
this.druationTime = this.formatSeconds(duration);
//console.log(this.druationTime,'this.druationTime');
this.currtime = this.formatSeconds(second);
},
//拖动过程中触发的事件
sliderChanging(e) {
@@ -98,7 +180,7 @@
},
// 拖动slider完成后触发
sliderChange(e) {
var duration=this.live.liveRoomRecordList[0].duration;
var duration=this.curVideo.duration;
var second=e.detail.value / 100 * duration;
if (duration) { //完成拖动后,计算对应时间并跳转到指定位置
this.videoContext.seek(second);
@@ -106,58 +188,171 @@
this.updateState= true //完成拖动后允许更新滚动条
this.druationTime = this.formatSeconds(duration);
this.currtime = this.formatSeconds(second);
}
else { }
}
},
onFullScreen(e) {
this.fullScreenFlag=e.detail.fullScreen;
let divId='videowatermark';//水印
let full=e.detail.fullScreen;
let divControlId='xplayer-control';
let box=document.getElementById('xvideoPlayer-box');
let control=document.getElementById(divControlId);
let $this=this;
setTimeout(() => {
var div = document.getElementById("xvideoPlayer");
var div1 = div.firstChild;
//水印
if(full){
if($this.watermark){
var div3 = document.createElement("div");
div3.id =divId;
div3.setAttribute("class", "fullmark");
div3.innerHTML='';
for(var i=0;i<4;i++){
div3.innerHTML+='<div style="color:#ffffff;width: 40%;height: 155px;padding-left:60px;padding-top:50px; display: flex;justify-content: center; transform: rotate(-36deg);font-size:20px;">'+$this.userInfo.name+$this.userInfo.code+'</div>';
}
div3.style.cssText = "position:absolute;pointer-events: none; width: 100%;height: 100%;top:0;left:0;bottom: 0;right: 0; display: flex;justify-content: center;flex-wrap: wrap;overflow: hidden; opacity:0.3;padding-top:10px";
div1.appendChild(div3);
}
//添加控制条
div1.appendChild(control);
}else{
var hasControlDiv=div1.querySelector("#"+divControlId);
if(hasControlDiv){
box.appendChild(hasControlDiv);
}
if($this.watermark){
var markDiv=div1.querySelector("#"+divId);
if(markDiv){
div1.removeChild(markDiv);
}
}
}
},200);
this.$emit('fullscreenchange',e);
//this.fullScreenFlag ? this.videoContext.exitFullScreen() : this.videoContext.requestFullScreen();
// this.fullScreenFlag ? this.bool=true : this.bool=false;
//this.fullScreenFlag=!this.fullScreenFlag;
},
error(e){
console.log(e,'播放错误');
this.$emit('error',e);
},
onTouchend(e){
if(this.contrlShowTimeout!=null){
window.clearTimeout(this.contrlShowTimeout);
}
if(!this.fullScreenFlag){
this.contrlShow=!this.contrlShow;
}else{
if(!this.contrlShow){
this.contrlShow=show;
}
}
// this.onPlayerPause()
// this.touchNum ++
// let $this=this;
// setTimeout(()=>{
// if($this.touchNum == 1){
// // console.log('单击')
// }else if($this.touchNum >= 2){
// if($this.playing){
// $this.onPause()
// } else {
// $this.onPlay()
// }
// }
// this.touchNum = 0
// },250)
},
onLoad(e){
this.contrlShow=false;
this.$emit('loadeddata',e);
},
onMetaLoad(e){
this.curVideo.duration=Number(e.detail.duration);
this.druationTime = this.formatSeconds(this.curVideo.duration);
this.contrlShow=true;
this.$emit('loadedmetadata',e);
},
onControlsToggle(e){
console.log(e,"ControlsToggle");
},
// 开始
contrPlay(){
onPlay(){
this.videoContext.play();
this.palyFlag=false;
this.playing=true;
let $this=this;
if(this.contrlShow){
this.contrlShowTimeout=window.setTimeout(function(){
$this.contrlShow=false;
},5000);
}
this.$emit('play')
},
// 暂停
pause() {
this.videoContext.pause(); //站厅播放
this.palyFlag=true;
onTimeUpdate(e){
this.videoUpdate(e);
this.$emit('timeupdate',e)
},
stop(){
this.videoContext.stop(); //
onPause() {
this.playing=false;
this.$emit('pause')
},
onEnded(){
this.playing=false;
this.$emit('ended')
}
}
}
</script>
<style lang="scss" scoped>
.process-container{
width:100%;
padding:1% 2% 1% 2%;
height:60rpx;
max-height:60rpx;
position:absolute;
bottom:40rpx;
left:0;
right:0;
z-index:13;
display:flex;
align-items: center;
background:rgba(59, 57, 57, 0.2);
.video-box{
width: 100%;
height: 100%;
position: relative;
}
.screen{
position: relative;
}
.screen-full{
position:static;
}
.process-container{
width:100%;
padding:1% 2% 1% 2%;
height:60rpx;
max-height:60rpx;
position:absolute;
bottom:0rpx;
color:#ffffff;
left:0;
right:0;
z-index:9999;
display:flex;
align-items: center;
background:rgba(59, 57, 57, 0.2);
}
.process-container image{
display:inline-block;
flex:1;
max-width:50rpx;
max-height:50rpx;
text-align:center;
max-width:30rpx;
max-height:30rpx;
text-align:center;
}
.slider-container{
z-index:13;
height:60rpx;
margin-bottom:10rpx;
flex:6;
max-width:58%;
max-width:50%;
}
.video-controls-play{
.controller-play{
width: 8%;
}
.controller-screen{
width: 10%;
}
.currtime{
color: #ffffff;
font-size: 22rpx;
@@ -174,18 +369,47 @@
line-height: 60rpx;
text-align: center;
}
.video_back{
display:block;
width:60rpx;
height:60rpx;
left:5rpx;
top:15rpx;
position:absolute;
text-align:center;
z-index:19;
.player-speed{
position: relative;
color: #e5e5e5;
padding: 0 0.4rem;
transition: color 0.3s;
height: 22px;
}
.video_back image{
width:44rpx;
height:44rpx;
.btn-speed:hover .speed-control {
// visibility: visible;
}
.speed-control {
position: absolute;
//top: 180px;
transition: visibility 0.3s;
transform: translate(-50%, -100%);
}
.speed-control .speed-control-list {
list-style: none;
color: #e5e5e5;
width: 50px;
font-size: 12px;
text-align: left;
padding: 0px 0px 0px 5px;
margin: 0;
overflow: hidden;
border-radius: 4px;
background: rgba(21, 21, 21, 0.8);
}
.speed-control .speed-control-list .li {
position: relative;
display: block;
height: 25px;
line-height: 25px;
}
.speed-control .speed-control-list .li:hover {
color: #fff;
background: rgba(99, 99, 99, 0.8);
}
.speed-control .speed-control-list .li.current {
color: var(--primaryColor);
}
</style>