课程页面留言板

This commit is contained in:
@fawn-nine
2024-06-13 16:08:41 +08:00
parent f8e165f758
commit 714bf5562f
3 changed files with 460 additions and 94 deletions

View File

@@ -20,6 +20,7 @@
data() {
return {
// windowWidth:320,
emojilist:emojiList1,
list1: [
[1,2,3],[4,5,6],
@@ -56,7 +57,8 @@
},
mounted() {
console.log('jihuo')
// this.windowWidth = uni.getSystemInfoSync().windowWidth;
const query = uni.createSelectorQuery().in(this);
query.select('.emotion-box').boundingClientRect(data => {
console.log(this.windowWidth / 10);

View File

@@ -3,23 +3,23 @@
<swiper class="guide_pages_swiper" indicator-dots="true" indicator-color="#d1d1d1" indicator-active-color="#54a966">
<swiper-item>
<view class="guide_pages_bg1">
吴门医述
<!-- 吴门医述
<br>
让阅读无处不在
让阅读无处不在 -->
</view>
</swiper-item>
<swiper-item>
<view class="guide_pages_bg2">
吴门医述
<!-- 吴门医述
<br>
古今一统中西互参
古今一统中西互参 -->
</view>
</swiper-item>
<swiper-item>
<view class="guide_pages_bg3">
吴门医述
<!-- 吴门医述
<br>
和光同尘普惠人间
和光同尘普惠人间 -->
</view>
<button v-if="screenHeight > 667" class="guide_pages_close close_1624" @click="onClose">开始使用</button>
<button v-else class="guide_pages_close close_btj" @click="onClose">开始使用</button>

View File

@@ -100,68 +100,54 @@
</view>
</view>
<uni-section class="mb-10 graybg" title="留言板" type="line">
<template v-slot:right>
<view class="flexbox " style="align-items: center;" @click="addSay()">
<u-icon name="edit-pen" color="#2979ff" size="28"></u-icon>
<text>发布留言</text>
</view>
</template>
</uni-section>
<view class="liuyanBox">
<view class="box">
<view class="firstLeve flexbox leve">
<view class="box" v-if="sayList.length > 0">
<view class="firstLeve flexbox leve" v-for="(item, index) in sayList" :key="index">
<view class="imgbox">
<view class="img">
<image src="@/static/logo.png" mode="aspectFit"></image>
<image :src="item.user.avatar" mode="aspectFit"></image>
</view>
</view>
<view class="contentBox">
<view class="name">
这是名字这是名字这是名字
{{item.user.name}}
</view>
<view class="content">
这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容
<view class="content" v-if="item.content != ''">
<rich-text class="content" :nodes="formatRichText(item.content)"></rich-text>
</view>
<view class="imagesList flexbox" v-if="item.images !=''">
<view class="item" v-for="(item2, index2) in item.imgList" :key="index2">
<image @click="previewImage(item2)" :src="item2" mode="widthFix"
style="width: 80rpx; height: 80rpx;"></image>
</view>
</view>
<view class="others flexbox">
<view class="dianzan flexbox">
<!-- <u-icon name="heart-fill" color="#999" size="24"></u-icon> -->
<u-icon name="heart" color="#999" size="24"></u-icon>
<text>387</text>
<u-icon v-if="item.support" name="heart-fill" color="#ff5500" size="24"></u-icon>
<u-icon v-else name="heart" color="#999" size="24"></u-icon>
<text>{{item.supportCount}}</text>
</view>
<view class="pinglun flexbox" @click="addSay()">
<view class="pinglun flexbox" @click="addSay(item)">
<!-- <u-icon name="chat-fill" color="#999" size="24"></u-icon> -->
<u-icon name="chat" color="#999" size="24"></u-icon>
<text>555</text>
<text>{{totalP}}</text>
</view>
<text>2024-06-12 0915</text>
<text>{{item.createTime}}</text>
</view>
</view>
</view>
<!-- -->
<view class="firstLeve flexbox leve">
<view class="imgbox">
<view class="img">
<image src="@/static/logo.png" mode="aspectFit"></image>
</view>
</view>
<view class="contentBox">
<view class="name">
这是名字这是名字这是名字
</view>
<view class="content">
这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容这是内容
</view>
<view class="others flexbox">
<view class="dianzan flexbox">
<!-- <u-icon name="heart-fill" color="#999" size="24"></u-icon> -->
<u-icon name="heart" color="#999" size="24"></u-icon>
<text>387</text>
</view>
<view class="pinglun flexbox">
<!-- <u-icon name="chat-fill" color="#999" size="24"></u-icon> -->
<u-icon name="chat" color="#999" size="24"></u-icon>
<text>555</text>
</view>
<text>2024-06-12 0915</text>
</view>
</view>
</view>
<!-- -->
</view>
<u-divider v-show="status == 2" text="已加载全部"></u-divider>
<u-divider v-show="status == 3" text="暂无留言数据"></u-divider>
<u-divider v-show="status == 1" text="加载中..."></u-divider>
</view>
<u-popup key="1" :show="pricespop" :round="10" @close="closePup">
<view class="proListPrice" v-if="proPriceList.length > 0">
@@ -194,28 +180,76 @@
<!-- 评论弹出 -->
<u-popup key="2" :show="sayVisible" :round="10" @close="sayclose">
<view class="contentBox">
<view class="" v-if="fatherSay.id != undefined">
<view class="" style="font-size: 26rpx; margin-bottom: 20rpx;">
<text>回复@{{fatherSay.user.name}} 的留言</text>
</view>
</view>
<view class="input_addIcon flexbox">
<view class="editorBox">
<editor id="editor" class="ql-container" placeholder="开始输入..." show-img-size
<editor id="editor" class="ql-container" placeholder="~ 和谐社会 友善发言 ~" show-img-size
show-img-toolbar show-img-resize @statuschange="onStatusChange" :read-only="readOnly"
@ready="onEditorReady">
</editor>
</view>
<view class="icon flexbox">
<u-icon v-show="!showEdit " @click="chooseImg" name="plus" color="#2979ff" size="28"></u-icon>
<u-icon v-show="showEdit " @click="editEditor" name="edit-pen" color="#2979ff" size="28"></u-icon>
<u-icon v-show="!showEdit " @click="chooseImg" name="plus" color="#2979ff"
size="28"></u-icon>
<u-icon v-show="showEdit " @click="editEditor" name="edit-pen" color="#2979ff"
size="28"></u-icon>
</view>
</view>
<!-- 选择表情还是图片 -->
<view class="chooseImgType flexbox" v-if="showImgType">
<text class="addEmoji" @click="addEmoji">表情</text><text @click="addPic">图片</text>
<view class="emojiBtn item flexbox" @click="addEmoji">
<view class="">
<view class="img">
<image src="@/static/biaoqing.png" mode="aspectFit"></image>
</view>
<view class="ss">
<text class="addEmoji">表情</text>
</view>
</view>
</view>
<view class="picBtn item flexbox" v-show="uploadPicLIst.length < 3">
<view class="" style="">
<u-upload @afterRead="addPic" @delete="deletePic" multiple :maxCount="3" width="40"
height="40" :previewFullImage="true">
</u-upload>
</view>
<!-- <view class="">
<uni-icons type="image" size="30" style="color: #666;"></uni-icons>
</view>
<view class="ss">
<text >图片</text>
</view> -->
</view>
</view>
<!-- 上传的图片 -->
<view class="" v-if="uploadPicLIst.length > 0">
<view class="" style="text-align: right;">
<text style="font-size: 24rpx; color: #999;">最多可上传3张图片哦</text>
</view>
<view class="upimgList flexbox">
<view class="item" v-for="(item, index) in uploadPicLIst" :key="index">
<image @click="previewImage(item.url)" :src="item.url" mode="widthFix"></image>
<span @click="deletePic(item,index)">×</span>
</view>
</view>
</view>
<!-- 表情 -->
<view class="emoji" v-if="showEmoji">
<text class="" @click="closeEmoji">关闭</text>
<emotion @emotion="handleEmj" :height="220" windowWidth="windowWidth">
<emotion @emotion="handleEmj" :height="220" :windowWidth="windowWidth">
</emotion>
</view>
<view class="sbmitBox">
<button @click="submitSay" type="default"> </button>
</view>
</view>
</u-popup>
@@ -239,7 +273,7 @@
data() {
return {
playData: {},
courseId: null,
catalogueId: null,
// fixed: false,
bgiStyle: {
background: '#fff'
@@ -275,10 +309,20 @@
// 评论
readOnly: false,
formats: {},
htmlContent: '', // 内容
showEmoji: false,
showImgType: false,
showEdit: false,
showPicsList: false,
windowWidth: 0,
uploadPicLIst: [], // 上传的图片列表
courseId: null,
sayList: [],
pPage: 1,
totalP: 0,
status: 88,
loadFlag: false,
fatherSay:{},
};
},
//第一次加载
@@ -288,9 +332,11 @@
this.windowWidth = uni.getSystemInfoSync().windowWidth;
// this.pageTitle = e.title
console.log(e, '传入分类id')
this.courseId = e.id
// this.getCateList(this.courseId)
this.getData(e.id)
this.getSuperMarketList()
this.getSayList()
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
@@ -309,6 +355,13 @@
uni.hideTabBar();
},
onReachBottom() {
console.log('触底');
if (this.status != 2) {
this.pPage++
this.getSayList()
}
},
components: {
// musicPlay
emotion,
@@ -317,6 +370,165 @@
//方法
methods: {
// 评论
// 提交
submitSay() {
this.editorCtx.getContents({
success: (res) => {
console.log("save = >", res);
this.htmlContent = res.html
},
})
if (this.htmlContent == '' && this.uploadPicLIst.length == 0) {
uni.showToast({
icon: 'none',
title: '您未输入内容哦'
})
return
}
let images = ''
if (this.uploadPicLIst.length > 0) {
let list = this.uploadPicLIst.map(item => item.url)
images = list.join()
}
console.log(images, 'images')
let forUserId = null
let pid = 0
forUserId = this.userInfo.id
if(this.fatherSay.id != undefined){
forUserId = this.fatherSay.user.id
pid = this.fatherSay.id
}
$http.request({
url: "common/courseGuestbook/addCourseGuestbook",
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data: {
"type": 0, //类型0课程1章节
"courseId": this.courseId,
"chapterId": "",
"pid": pid,
"userId": this.userInfo.id,
"forUserId": forUserId,
"content": this.htmlContent, //内容
"images": images //图片的合集,逗号分隔
},
header: { //默认 无 说明:请求头
'Content-Type': 'application/json'
},
}).then(res => {
if (res.code == 0) {
this.htmlContent = ''
this.uploadPicLIst = []
this.editorCtx.clear()
uni.showToast({
icon: 'success',
title: '提交成功'
})
}
this.sayList.unshift(res.courseGuestbook)
// console.log(res, '提交成功',this.sayList);
this.sayVisible = false
// this.getSayList()
// 获得的新实例,插入到数组的前面
}).catch(e => {
uni.showToast({
icon: 'error',
title: '提交失败'
})
console.log('提交报错');
})
},
// 查询课程的评论
getSayList() {
if (this.loadFlag) {
console.log('有未完成的进程');
return
}
this.loadFlag = true
this.status = 1
$http.request({
url: "common/courseGuestbook/getCourseGuestbookList",
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data: {
"limit": 15,
"page": this.pPage,
"courseId": this.courseId,
"chapterId": "",
"userId": this.userInfo.id //登陆人id用与判断评论是否被登陆人点赞
},
header: { //默认 无 说明:请求头
'Content-Type': 'application/json'
},
}).then(res => {
console.log('sayList =>', res);
if (res.code == 0) {
if (res.page.records.length > 0) {
let myList = res.page.records
this.totalP = res.page.total
myList.map((item) => {
if (item.images != '') {
item.imgList = item.images.split(',')
}
})
this.sayList = this.sayList.concat(myList)
console.log('this.sayList处理后 =》 ', this.sayList)
if (res.page.pages > this.pPage) {
this.status = 0
} else {
this.status = 2
}
} else {
this.status = 3 // 暂无数据
}
}
this.loadFlag = false
}).catch(e => {
console.log('获取留言失败');
this.loadFlag = false
})
},
previewImage(url) {
console.log(url)
uni.previewImage({
urls: [url],
longPressActions: {
itemList: ['很抱歉,暂不支持保存图片到本地'],
success: function(res) {
// console.log(res,'+++++')
}
}
});
},
deletePic(val, i) {
console.log('删除图片');
this.uploadPicLIst.splice(i, 1)
},
addPic(e) {
console.log('添加图片');
let that = this
for (var i = 0; i < e.file.length; i++) {
//console.log(i,e.file[i].url)
uni.uploadFile({
url: this.$baseUrl + 'oss/fileoss',
filePath: e.file[i].url,
//files:e.file,
name: 'file',
formData: {},
success: (res) => {
that.uploadPicLIst.push({
url: JSON.parse(res.data).url
})
// this.showPicsList = true
console.log(that.uploadPicLIst, 'that.uploadPicLIst')
},
fail: (error) => {
console.log('上传失败', error)
}
});
}
},
// 获得输入的表情数组
handleEmj(i) {
console.log(i, 'i---------');
@@ -345,20 +557,18 @@
chooseImg() {
this.showImgType = true
this.showEdit = true
uni.hideKeyboard() // 隐藏键盘
},
editEditor() {
this.showImgType = false
this.showEdit = false
this.showEmoji = false
// 显示键盘
},
closeEmoji() {
this.showEmoji = false
this.showEdit = false
},
addPic(){
// 上传图片
},
addEmoji() {
this.showEmoji = true
this.showImgType = false
@@ -372,22 +582,26 @@
this.readOnly = !this.readOnly
},
onEditorReady() {
// #ifdef MP-BAIDU
this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editor');
// #endif
// // #ifdef MP-BAIDU
// this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editor');
// // #endif
// #ifdef APP-PLUS || MP-WEIXIN || H5
uni.createSelectorQuery().select('#editor').context((res) => {
this.editorCtx = res.context
this.editorCtx.clear()
}).exec()
// #endif
},
// end
addSay(item) {
this.sayVisible = true
item ? this.fatherSay = item : ''
console.log('fatherSay =>',this.fatherSay);
},
sayclose() {
this.sayVisible = false
this.fatherSay = {}
},
getSuperMarketList() {
$http.request({
@@ -430,10 +644,10 @@
this.pageTitle = this.course.title
this.librayList = res.data.catalogues
if (this.librayList.length > 0) {
this.courseId = this.librayList[0].id
this.catalogueId = this.librayList[0].id
this.curId = this.librayList[0].id
this.curIndex = 0
this.getChapterList(this.courseId)
this.getChapterList(this.catalogueId)
}
}
@@ -597,22 +811,172 @@
url: `${url}`
});
},
formatRichText(html) { //控制图片大小
let newContent = html.replace(/<img[^>]*>/gi, function(match, capture) {
match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
return match;
});
newContent = newContent.replace(/style="[^"]+"/gi, function(match, capture) {
match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi,
'max-width:100%;');
return match;
});
newContent = newContent.replace(/<br[^>]*\/>/gi, '');
newContent = newContent.replace(/\<img/gi,
'<img style="max-width:40rpx;height:40rpx;display:inline-block;margin:10rpx auto;"');
return newContent;
},
},
};
</script>
<style lang="scss" scoped>
@import '@/style/mixin.scss';
::v-deep .contentBox {
.ql-editor{font-size: 26rpx ; font-style: normal; min-height: 50rpx !important; padding: 20rpx;}
img{width: 20px;}
.ql-editor {
font-size: 26rpx;
font-style: normal;
min-height: 50rpx !important;
padding: 20rpx;
}
.input_addIcon{}
.editorBox{width: calc(100vw - 100rpx);}
.ql-container{ min-height: 50rpx !important; height: auto!important; border: 1px solid #eee; border-radius: 50rpx;}
img {
width: 20px;
}
.u-upload__button {
margin: 0 auto;
}
}
.chooseImgType {
margin-top: 20rpx;
.item {
text-align: center;
margin-right: 20rpx;
padding: 10rpx;
box-sizing: border-box;
justify-content: center;
align-items: center;
width: 60px;
border: 1px solid #eee;
height: 60px;
text-align: center;
border-radius: 20rpx;
background-color: #f4f5f7;
// background-color: red;
text {
font-size: 24rpx;
display: inline-block;
width: 100%;
margin-top: -10rpx;
}
.img {
margin: 0 auto;
}
.ss {
line-height: 20rpx;
color: #666;
}
}
}
.sbmitBox {
button {
margin-top: 20rpx;
margin-bottom: 20rpx;
@include theme("btn_bg");
color: #fff;
}
}
.upimgList {
margin-top: 15px;
.item {
border: 1px solid #eee;
padding: 10rpx;
margin-right: 20rpx;
width: 100rpx;
height: 100rpx;
position: relative;
image {
width: 100%;
height: 100rpx;
}
span {
display: inline-block;
width: 20px;
height: 20px;
position: absolute;
right: -10px;
top: -10px;
z-index: 1;
border: 1px solid #eee;
border-radius: 20rpx;
background-color: #fff;
line-height: 20px;
font-size: 26rpx;
text-align: center;
}
}
}
.emojiBtn {
.img {
width: 50rpx;
height: 50rpx;
image {
width: 100%;
height: 50rpx;
}
}
}
.editorBox {
width: calc(100vw - 100rpx);
}
.ql-container {
min-height: 50rpx !important;
height: auto !important;
border: 1px solid #eee;
border-radius: 50rpx;
}
.contentBox {
padding: 20rpx;
.icon{width: 80rpx; justify-content: center; margin-left: 10rpx; height: 80rpx; align-items: center; border: 1px solid #eee; border-radius: 50rpx;}
.addEmoji{margin-right: 20rpx;}
.icon {
width: 80rpx;
justify-content: center;
margin-left: 10rpx;
height: 80rpx;
align-items: center;
border: 1px solid #eee;
border-radius: 50rpx;
}
.addEmoji {
margin-right: 20rpx;
}
.imagesList {
.item {
margin-right: 20rpx;
}
}
}
//