Files
nuttyreading-html/pages/clock/clock.vue
@fawn-nine 7b9044f4df 2023.09.01
2023-09-01 18:04:41 +08:00

844 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<z-nav-bar title="读书打卡"></z-nav-bar>
<!-- 仿钉钉打卡日历组件 -->
<view class="calendar_container">
<!-- <zsy-calendar @change="change" /> -->
<!-- <clock-date></clock-date> -->
<view class="calendar_info">
<text class="title">读书打卡</text>
<view class="dakaBtn" @tap="kuickSign()" v-if="signList.indexOf(currentDay) == -1">
<u-icon name="checkbox-mark" color="#55aa7f" size="24" style="display: inline;"></u-icon>
<text>签到</text>
</view>
<view v-else class="haveSignText">
<text>今天已签到</text>
</view>
</view>
<scroll-view class="scroll-view_H flexbox" scroll-x="true" @scroll="scroll" :scroll-left="scrollLeft">
<view class="" style="padding: 0 6rpx; display: inline-block; width: 20%; box-sizing: border-box; " v-for="(item,index) in 365">
<view
:class="['item', signList.indexOf(index+1) != -1 ? 'havSign' : '',
currentDay == index+1 && signList.indexOf(index+1) == -1 ? 'current' : '',
linshiDay == index+1 ? 'linshiDay':'']" @click="getInfo(index+1)">
<span class="day"> <em>{{index+1}}</em> </span>
<u-icon v-if="signList.indexOf(index+1) != -1" name="checkbox-mark" color="#fff" size="28" style="margin: 0 auto; width: 28px; text-align: center;"></u-icon>
<span v-if="signList.indexOf(index+1) == -1 && currentDay > index+1" class="buka">未签</span>
<span v-if="currentDay < index+1" class="weidaka">未开始</span>
<span v-if="currentDay == index+1 && signList.indexOf(index+1) == -1" class="daka" @click="kuickSign()">签到</span>
</view>
</view>
</scroll-view>
</view>
<view class="container1">
<view class="task" v-if="taskInfo !== {}">
<view class="title" v-if="taskInfo.heading">
{{taskInfo.heading}}
</view>
<view class="video " v-if="taskInfo.video">
<!-- 视频形式的任务 -->
<view class="taskinfo">
<video id="myVideo" :poster="poster" v-show="!addTextShow"
:src="taskInfo.video"
@error="videoErrorCallback" controls></video>
</view>
</view>
<view class="image " v-if="taskInfo.images">
<!-- 图片形式的任务 -->
<image :src="taskInfo.images" style="width: 100%;" mode="aspectFit"></image>
</view>
<!-- <view class="voice ">
音频形式的任务
<audio style="text-align: center; width: 100%;" :src="currentAudio.src"
:poster="currentAudio.poster" :name="currentAudio.name" :author="currentAudio.author"
:action="audioAction" controls></audio>
</view> -->
<view class="txt" v-if="taskInfo.content" v-html="taskInfo.content"></view>
</view>
<view class="subContent">
<text class="clockTitle">-- 我的签到 --</text>
<!-- 未打卡 -->
<!-- 已打卡 -->
<view class="had" v-if="show">
<view class="item">
<h3>#第三课专业变现你的专业 = 超级杠杆 第一笔只是财富#</h3>
<view class="content">
借我一个暮年借我碎片
借我瞻前与顾后借我执拗如少年
借我后天长成的先天借我变如不曾改变
借我素淡的世故和明白的愚借我可预知的险
借我悲怆的磊落借我温软的鲁莽和玩笑的庄严
借我最初与最终的不敢借我不言而喻的不见
借我一场秋啊可你说这已是冬天
</view>
<view class="images flexbox">
<image @click="previewImage()"
src="https://picx.zhimg.com/70/v2-92392172531ba8e252e3f9afaa4232d2_1440w.awebp?source=172ae18b&biz_tag=Post"
mode="aspectFill"></image>
<image
src="https://picx.zhimg.com/70/v2-92392172531ba8e252e3f9afaa4232d2_1440w.awebp?source=172ae18b&biz_tag=Post"
mode="aspectFill"></image>
</view>
<view class="opBtns flexbox">
<span class="flexbox"><u-icon name="clock" color="#b3b3b3"></u-icon>2023-08-23 14:01</span>
</view>
</view>
</view>
</view>
<!-- 他人的打卡记录 -->
<view class="" v-if="commentsList && commentsList.length > 0">
<view class="pingjiaBox" v-for="(item, index) in commentsList" :key="index">
<view class="flexbox">
<view class="touxiang">
<image :src="item.avatar" mode="aspectFit"></image>
<text class="username nowrap ">{{item.name}}</text>
</view>
<view class="contentBox">
<div class="pjimgs flexbox">
<view class="item" v-for="(item1,index) in item.images">
<image v-if="item1.length > 10" @click="previewImage(item1)" :src="item1" mode="aspectFill" style="width:100%; height: 50px;"></image>
</view>
</div>
<view class="content" v-html="item.phtml"></view>
<text class="time">{{item.createdate}}</text>
</view>
</view>
<!-- 显示追平 -->
<view class="zhuiping item" v-if="item.zphtml != ''" style="padding-left: 50px;">
<h5 style="color: #dbdbdb; margin:10px;">追评内容</h5>
<view class="flexbox">
<view class="contentBox">
<view class="content" v-html="item.zphtml"></view>
<text class="time">{{item.followUpdate}}</text>
</view>
</view>
</view>
</view>
</view>
<view class="quesheng" v-else>
<text>暂无评价~</text>
</view>
</view>
<u-popup mode="bottom" :show="addTextShow" :round="10" @close="addTextShow=false">
<view class="tanchu">
<view class="dp_title">今日签到随想</view>
<view style="max-height: 1000rpx;overflow-y: scroll;">
<!-- 提交 -->
<view class="padding-bottom-sm flex padding-lr-sm" style="border-bottom: 1px solid #EEEEEE;">
<view class="mb30">
<!-- <uni-file-picker :auto-upload="false" ref="files" @delete="deleteImg" limit="5" @success="upSuccess" @select="select" v-model="Pform.img" fileMediatype="image" :image-styles="imageStyles"/> -->
<u-upload :fileList="formData.images" @afterRead="afterRead" @delete="deletePic" multiple
:maxCount="4" width="80" height="80" :previewFullImage="true">
</u-upload>
</view>
<view class="flex-sub flexbox mb30">
<i @click="showEmj()" :class="emojiIcon"></i>
<!-- <input type="text" @focus="InputFocus" @blur="InputBlur" v-model="message" @input="textareaBInput" placeholder-style="font-size:24rpx;color:#aaaaaa;" placeholder="请输入您要发送的内容"></input> -->
<textarea style="border: 1px solid #EEEEEE;" class="textarea" v-model="formData.content"
@focus="InputFocus" @blur="InputBlur" @input="textareaBInput"
placeholder-style="font-size:24rpx;color:#aaaaaa;" placeholder="请输入内容"></textarea>
</view>
<view>
<u-button type="success" @click="goToSign">提交</u-button>
</view>
</view>
<view style="position: relative;">
<emotion @emotion="handleEmj" :height="220" v-if="isShowEmj" :windowWidth="windowWidth">
</emotion>
</view>
</view>
</view>
</u-popup>
<view class="leaveBtn" v-if="!addTextShow">
<button type="primary" plain="true" @click="addTextShow = true">说点什么</button>
</view>
<music-play :playData="playData"></music-play>
<!-- <z-navigation></z-navigation> -->
</view>
</template>
<script>
import $http from '@/config/requestConfig.js';
import emotion from '@/bkhumor-emojiplus/components/bkhumor-emojiplus/bkhumor-emojiplus.vue';
import zsyCalendar from '@/components/zsy-calendar/zsy-calendar'
import clockDate from '@/components/clockDate.vue'
import musicPlay from '@/components/music.vue'
import {
mapState
} from 'vuex';
export default {
data() {
return {
commentsList:[], // 他人的打卡列表
addTextShow: false, // 说点什么弹出层
show: false,
scrollLeft: 0, // 距离左侧的距离
currentDay:1, // 当前打卡位置
currentTid:null, // 今天的任务id
emojiIcon: 'cuIcon-emoji',
windowWidth: 0,
taskInfo:{
heading:''
},
emoji: [],
signList:[], // 已打卡天
linshiDay:null,
page: 1,
bookid: null,
windowHeight: 500,
isShowEmj: false,
playData: {},
videoContext: null,
innerAudioContext: null, // 音频对象
poster: '',
formData: {
// 打卡表单
content: '',
images: []
},
currentAudio: {
poster: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png',
name: '致爱丽丝',
author: '暂无',
src: 'https://bjetxgzv.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3',
},
audioAction: {
method: 'pause'
},
// 校验规则
rules: {
content: {
rules: [{
required: true,
errorMessage: '内容不能为空'
}]
},
},
}
},
onLoad(e) {
this.bookid = e.bookid
this.windowWidth = uni.getSystemInfoSync().windowWidth;
this.getmySign()
},
onReady() {
this.videoContext = uni.createVideoContext('myVideo')
this.innerAudioContext = uni.createInnerAudioContext();
this.innerAudioContext.autoplay = false;
},
computed: {
...mapState(['userInfo'])
},
methods: {
// 放大图片
previewImage(url){
console.log(url)
uni.previewImage({
urls: [url]
});
},
// 获取打卡参数
getmySign(){
let data = {
'bookId': this.bookid,
'userId': this.userInfo.id
}
this.$http
.post('book/clockinPunch/clockindays', data)
.then(res => {
if (res.code == 0) {
this.currentDay = res.daysBetween
this.signList = res.dayslist
console.log(res, '打卡参数')
let zheng = Math.floor(this.currentDay / 5)
let yu = this.currentDay % 5
if(this.currentDay <=5){this.scrollLeft = 0}
if(zheng >= 1 && yu > 0){
// 不是前五个,并且不能整除
this.scrollLeft = (this.windowWidth - 30) * zheng
}
if(zheng > 1 && yu == 0){
this.scrollLeft = (this.windowWidth - 30) * (zheng - 1)
}
// console.log(zheng, yu, this.scrollLeft, this.windowWidth, 'this.scrollLeft')
this.getTask(this.currentDay)
this.getAllSign(this.currentDay)
}
});
},
// 获取签到详情
getInfo(index){
if(this.currentDay < index){
uni.showToast({
title:'未来日期不可签到',
icon: 'none'
})
}else{
this.linshiDay = index
this.getTask(index)
this.getAllSign(index)
}
},
// 获取某天的签到列表信息
getAllSign(index){
let data = {
'bookid': this.bookid,
'limit': 5,
'page': this.page,
'taskid': index
}
console.log(data)
this.$http
.post('book/clockin/applist', data)
.then(res => {
if (res.code == 0) {
console.log(res, '所有人打卡信息')
this.commentsList = res.page.list
}
});
},
// 获取对应签到内容
getTask(index){
let data = {
'bookid': this.bookid,
'days': index
}
console.log(data)
this.$http
.post('book/task/applist', data)
.then(res => {
if (res.code == 0) {
console.log(res, '任务信息')
this.taskInfo = res.page.list[0]
this.taskInfo.video != ''? this.poster = this.taskInfo.video + "?x-oss-process=video/snapshot,t_0,f_jpg" : ''
}
});
},
// 快捷签到
kuickSign(){
let data = {
"bookId": this.bookid,
"userId": this.userInfo.id,
"tid": this.taskInfo.id,
"days":this.currentDay
}
// console.log(data,'data')
$http.request({
url : 'book/clockinPunch/save',
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: { //默认 无 说明:请求头
'Content-Type': 'application/json'
},
}).then(res => {
if (res.code == 0) {
//console.log(res, '快捷签到')
uni.showToast({
title:res.msg
})
this.addTextShow = false
this.formData.content = ''
this.formData.images = []
this.getmySign()
this.getAllSign(this.currentDay)
}
});
},
// 说点什么
goToSign() {
let data = {
'bookId': this.bookid,
"userId": this.userInfo.id,
"taskId": this.currentDay,
"content": this.formData.content,
"images": this.formData.images.join(),
}
// console.log(data,'data')
var surl = ''
if(this.signList.indexOf(this.currentDay) != -1){
surl='book/clockin/update'
}else{
surl = 'book/clockin/save'
}
$http.request({
url : surl,
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: { //默认 无 说明:请求头
'Content-Type': 'application/json'
},
}).then(res => {
if (res.code == 0) {
//console.log(res, '快捷签到')
uni.showToast({
title:res.msg
})
this.addTextShow = false
this.formData.content = ''
this.formData.images = []
this.getmySign()
this.getAllSign(this.currentDay)
}
});
},
scroll(e) {
},
// 获得输入的表情数组
handleEmj(i) {
console.log(i, 'i---------');
// this.inputValue = i
// console.log(this.inputValue);
if (i.emotioni == '[em_98]') {
//匹配最后一个表情符号并删除11。
this.formData.content = this.formData.content.replace(/(\[[^\]]+\]|[\s\S])$/, '');
if (this.emoji.length > 0) {
this.emoji = this.emoji.slice(0, -1)
}
} else {
this.emoji.push({
'tag': i.emotion,
'name': i.emotioni
})
// console.log(this.emoji,'this.emoji')
this.formData.content += i.emotioni;
/// this.Pform.html += i.emotion
}
},
// 放大图片
previewImage(url) {
console.log(url)
uni.previewImage({
urls: [url]
});
},
showEmj() {
let bool = !this.isShowEmj;
if (bool) {
this.emojiIcon = 'cuIcon-keyboard';
} else {
this.emojiIcon = 'cuIcon-emoji';
}
this.isShowEmj = bool;
this.$emit('show')
},
textareaBInput(e) {
this.formData.comment = e.detail.value
},
InputBlur(e) {
},
InputFocus(e) {
this.isShowEmj = false;
this.emojiIcon = 'cuIcon-emoji';
this.$emit('foc')
},
// 处理格式
getHtmlComment(comment) {
// 格式化html
// 这里处理 链接 换行符
let replacedStr = comment.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
// console.log(item, index)
var indexss = emojiList1.findIndex(item1 => item1.alt === item)
// console.log(indexss, 'indexss')
return '<img src="https://www.nuttyreading.com/emojis/emojis/qq/' + emojiList1[indexss].url +
'" width="18rpx">';
});
// console.log(replacedStr,'replacedStr')
return replacedStr.replace(/(\r\n)|(\n)/g, '<br>');
},
// 提交打卡
submit() {
this.$refs['formData'].validate().then(res => {
console.log('success', res);
uni.showToast({
title: `校验通过`
})
}).catch(err => {
console.log('err', err);
})
},
deletePic() {
let that = this
that.formData.images.splice(0, 1)
//console.log(that.Pform.img)
},
afterRead(e) {
//console.log(e)
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.formData.images.push({
url: JSON.parse(res.data).url
})
}
});
}
},
videoErrorCallback: function(e) {
uni.showModal({
content: e.target.errMsg,
showCancel: false
})
},
// 日历选中日期改变事件回调
change(e) {
console.log(e)
}
},
components: {
musicPlay,
zsyCalendar,
emotion,
clockDate
},
}
</script>
<style lang="scss" scoped>
.quesheng{text-align: center; margin-top: 100rpx; color: #8b8a91;}
.haveSignText{color: #999 ;}
.calendar_info {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
.dakaBtn {
color: #55aa7f;
display: flex;
padding: 3rpx 5rpx;
border: #55aa7f 1px solid;
border-radius: 10rpx;
}
}
.scroll-view_H {
white-space: nowrap;
margin: 20px 0;
width: 100%;
.item {
border: 1px dashed #999;
width: calc(100% - 6rpx);
// margin: 0 6rpx;
text-align: center;
display: inline-block;
background-color: #F0FDFF;
border-radius: 20rpx;
padding: 6rpx 3rpx;
.day {display: block;
font-size: 26rpx;
color: #999;
em {
font-size: 36rpx;
font-style: normal;
font-weight: bold;
padding-right: 2px;
}
}
.checkbox-mark {
display: none;
}
.buka {
display: inline-block; padding: 0 6rpx;
color: #888;
// border: 1px solid #888;
margin: 10px 0;
border-radius: 15rpx;
margin-bottom: 0; ;
}
.weidaka {
color: #A3B4B5;
margin: 10px 0; font-size: 24;
border-radius: 20rpx;
margin-bottom: 0;
display: block;
}
.daka{
display: inline-block; padding: 0 6rpx;
border: 1px solid #55aaff;
color: #55aaff;
margin: 10px 0;
border-radius: 20rpx;
margin-bottom: 0;
display: block;
}
}
.item.havSign {
border: 1px solid #55aa7f;
text-align: center;
display: inline-block;
background-color: #55aa7f;
border-radius: 20rpx;
padding: 6px 6px;
.day {
font-size: 26rpx;
color: #fff;
em {
font-size: 32rpx;
font-style: normal;
font-weight: bold;
padding-right: 2px;
}
}
.checkbox-mark {
display: block;
}
}
.item.current{
border: 1px solid #55aaff;
text-align: center;
display: inline-block;
background-color: #edf9ff;
border-radius: 20rpx;
padding: 6px 6px;
.day {
font-size: 26rpx;
color: #55aaff;
em {
font-size: 32rpx;
font-style: normal;
font-weight: bold;
padding-right: 2px;
}
}
}
.item.linshiDay{
border: 1px solid #55aaff;
text-align: center;
display: inline-block;
background-color: #55aaff;
border-radius: 20rpx;
padding: 6px 6px;
.day {
font-size: 26rpx;
color: #fff;
em {
font-size: 32rpx;
font-style: normal;
font-weight: bold;
padding-right: 2px;
}
}
.buka{color: #fff; }
}
}
.dp_title {
font-size: 32rpx;
margin-bottom: 50rpx;
color: #555;
text-align: center;
font-weight: bold;
}
.mb30 {
margin-bottom: 30rpx;
}
.tanchu {
padding: 40rpx 30rpx 40rpx 30rpx;
position: relative;
}
.cuIcon-emoji {
background: url(../../static/biaoqing.png) no-repeat;
background-size: contain;
display: block;
margin-right: 20rpx;
width: 30px;
}
.cuIcon-keyboard {
background: url(../../static/biaoqing.png) no-repeat;
background-size: contain;
display: block;
width: 30px;
}
.leaveBtn {
position: fixed;
width: calc(100% - 4px);
background: #fff;
bottom: 1rpx;
left: 1px;
z-index: 1;
}
.task {
margin-top: 40rpx 20rpx;
.taskinfo {
video {
width: 100%;
}
}
}
.subContent {
margin-top: 20rpx;
background-color: #fff;
overflow: hidden;
.clockTitle {
color: #55aa7f;
font-size: 38rpx;
text-align: center;
display: block;
margin-top: 30rpx;
}
}
.container1 {
.margin-top {
margin-top: 30rpx;
overflow: hidden;
}
}
.container {
padding: 30rpx;
}
.calendar_container {
//min-height: calc(60vh);
background-color: #fff;
//padding: 30rpx;
box-sizing: border-box;
padding-bottom: 20rpx;
border-radius: 20rpx;
margin-bottom: 20rpx;
}
.task {
padding: 30rpx 20rpx;
background-color: #f5f5f5;
background-color: #fff;
padding-bottom: 50rpx;
.title {
margin-top: 30rpx;
padding: 30rpx;
color: #002968;
background-color: #fff;
font-size: 46rpx;
padding: 20rpx;
}
.item {}
.video {
border-radius: 0 0 20rpx 20rpx;
}
.txt {
margin-top: 30rpx;
color: #666;
line-height: 50rpx;
}
}
.haveNo {
background: #fff;
.box {
height: 20vh;
display: flex;
align-items: center;
button {
width: 50%;
margin: 0 auto;
}
}
.subform {
padding: 0 20rpx;
margin-top: 30rpx;
.btns {
width: 400rpx;
margin: 0 auto;
margin-bottom: 40rpx;
justify-content: space-between;
}
}
}
.had {
padding: 60rpx;
margin-top: 30rpx;
background-color: #fff;
h3 {
color: #8c9a92;
font-size: 34rpx;
}
.content {
line-height: 60rpx;
margin-top: 30rpx;
font-size: 30rpx;
color: #0e0e15;
}
.images {
height: 150rpx;
overflow: hidden;
margin-top: 30rpx;
image {
width: 150rpx;
margin: 0 10rpx;
}
}
.opBtns {
margin-top: 30rpx;
span {
color: #b3b3b3;
padding-left: 20rpx;
font-size: 24rpx;
}
}
}
.flexbox {
display: flex;
}
</style>