阶段性上传

This commit is contained in:
@fawn-nine
2023-09-08 18:06:39 +08:00
parent 7b9044f4df
commit b0cc2b8663
62 changed files with 5075 additions and 506 deletions

26
App.vue
View File

@@ -20,6 +20,30 @@ export default {
} }
}) })
// 取出初始播放信息
uni.getStorage({
key: 'playingInfo',
success: function (res) {
console.log(res,'playingInfo本地初始化')
store.commit('setUserInfo',{'playingInfo': res.data})
store.commit('setUserInfo',{
'playTitle':res.data.chapterName,
'fengImg':res.data.images
})
console.log(store.state.userInfo,'初始化')
},
fail:function(e){
console.log(e,'playingInfo本地初始化失败')
store.commit('setUserInfo',{'playingInfo': {
'images':'../../static/icon/fengziIcon.jpg',
'chapterName':'暂无播放信息',
}})
store.commit('setUserInfo',{
'playTitle': '暂无播放信息',
'fengImg': '../../static/icon/fengziIcon.jpg'
})
},
})
// 取出播放列表 // 取出播放列表
uni.getStorage({ uni.getStorage({
key: 'playData', key: 'playData',
@@ -39,7 +63,7 @@ export default {
fail:function(e){ // 如果没有,就查询一下线上的播放记录 fail:function(e){ // 如果没有,就查询一下线上的播放记录
console.log('本地无数据'); console.log('本地无数据');
music.setList([]) music.setList([])
store.commit('setUserInfo',{'playingInfo': {'bookid':0,'chapterId':0}}); //store.commit('setUserInfo',{'playingInfo': {'bookid':0,'chapterId':0}});
store.commit('setUserInfo',{'playVisible': false}) store.commit('setUserInfo',{'playVisible': false})
// music.setCoverImg('../../static/icon/x1.jpg') // music.setCoverImg('../../static/icon/x1.jpg')
store.commit('setUserInfo',{ store.commit('setUserInfo',{

40
components/clockDate.vue Normal file
View File

@@ -0,0 +1,40 @@
<template>
<view>
<view class="calendar_swiper">
<swiper
key="normalSwiper"
circular
:style="{height: swiperHeight}"
:current="current"
:duration="duration"
:skip-hidden-item-layout="true"
@change="swiperChange"
>
<swiper-item v-for="(swiper, swiperIndex) in 3" :key="swiperIndex" class="swiper-item">
{{swiperIndex}}
</swiper-item>
</swiper>
</view>
</view>
</template>
<script>
export default {
name:"clockDate",
data() {
return {
current: 1,
duration:300,
swiperHeight:75
};
},methods:{
swiperChange(e){
console.log(e)
}
}
}
</script>
<style>
</style>

View File

@@ -127,11 +127,9 @@
}, },
created() { created() {
this.libLIst = this.$bgm.musicList this.libLIst = this.$bgm.musicList
this.fengImg = this.userInfo.fengImg this.fengImg = this.userInfo.fengImg
this.userInfo.playTimes ? this.setUserInfo({'currentTime': this.userInfo.playTimes}) : '' this.userInfo.playTimes ? this.setUserInfo({'currentTime': this.userInfo.playTimes}) : ''
console.log(this.userInfo.currentTime,'组件读到的历史记录')
}, },
computed: { computed: {
@@ -143,11 +141,7 @@
overTimer() { overTimer() {
this.duration = this.userInfo.duration this.duration = this.userInfo.duration
return calcTimer(this.userInfo.duration) return calcTimer(this.userInfo.duration)
}, },
// fengImg(){
// console.log(this.userInfo.fengImg,'-------------')
// return this.userInfo.fengImg
// }
}, },
watch: { watch: {

View File

@@ -6,7 +6,8 @@
<!--音频播放按钮处--> <!--音频播放按钮处-->
<view class="audo-top"> <view class="audo-top">
<!-- 播放封面 --> <!-- 播放封面 -->
<image @click="changeShow" style="width: 120rpx; height: 120rpx; margin-top: 0;" :class="['fengImg','fengmianBox','defaultBg', userInfo.playFlag ? 'playAnimate' : '']" :src="userInfo.fengImg" mode="aspectFill"></image> <image v-if="userInfo.fengImg && userInfo.fengImg != ''" @click="changeShow" style="width: 120rpx; height: 120rpx; margin-top: 0;" :class="['fengImg','fengmianBox','defaultBg', userInfo.playFlag ? 'playAnimate' : '']" :src="userInfo.fengImg" mode="aspectFill"></image>
<image v-else @click="changeShow" style="width: 120rpx; height: 120rpx; margin-top: 0;" :class="['fengImg','fengmianBox','defaultBg', userInfo.playFlag ? 'playAnimate' : '']" src="@/static/icon/fengziIcon.jpg" mode="aspectFill"></image>
<!-- <u-icon name="arrow-right" color="#61e781" size="28" v-else @click="changeShow"></u-icon> --> <!-- <u-icon name="arrow-right" color="#61e781" size="28" v-else @click="changeShow"></u-icon> -->
<!--上一首切换按钮--> <!--上一首切换按钮-->
@@ -77,9 +78,7 @@
created() { created() {
// this.fengImg = this.$music.getCoverImg() // this.fengImg = this.$music.getCoverImg()
this.fengImg = this.userInfo.fengImg this.fengImg = this.userInfo.fengImg
// this.libLIst = this.$music.getLibList()
this.libLIst = this.userInfo.myList this.libLIst = this.userInfo.myList
// console.log(this.userInfo.playIndex,'this.userInfo.playIndex')
}, },
mounted() { mounted() {
@@ -246,7 +245,7 @@
.nextMusic{width:50rpx;height:50rpx; display: none;} .nextMusic{width:50rpx;height:50rpx; display: none;}
} }
.fuchuang{position: fixed; padding-right: 10px; padding-left: 0; bottom:120rpx; right:0; z-index: 888; background-color:rgba(255, 255, 255, 1); } .fuchuang{position: fixed; padding-right: 10px; padding-left: 0; bottom:180rpx; right:0; z-index: 888; background-color:rgba(255, 255, 255, 1); }
.playAnimate{ .playAnimate{
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
animation: rotation 6s linear infinite; animation: rotation 6s linear infinite;

View File

@@ -28,14 +28,14 @@
path: '', path: '',
navigationList: [{ navigationList: [{
pagePath: 'pages/peanut/home', pagePath: 'pages/peanut/home',
iconPath: 'static/tab/icon1_n.png', iconPath: 'static/tab/tab1.png',
selectedIconPath: 'static/tab/icon1_y.png', selectedIconPath: 'static/tab/tab1-1.png',
text: '首页' text: '首页'
}, },
{ {
"pagePath": "pages/library/library", "pagePath": "pages/library/library",
"iconPath": "static/tab/icon3_n.png", "iconPath": "static/tab/tab2.png",
"selectedIconPath": "static/tab/icon3_y.png", "selectedIconPath": "static/tab/tab2-1.png",
"text": "我的图书" "text": "我的图书"
}, },
// { // {
@@ -46,15 +46,15 @@
// }, // },
{ {
pagePath: 'pages/bookShop/orderList', pagePath: 'pages/bookShop/orderList',
iconPath: 'static/tab/icon2_n.png', iconPath: 'static/tab/tab3.png',
selectedIconPath: 'static/tab/icon2_y.png', selectedIconPath: 'static/tab/tab3-1.png',
text: '我的订单' text: '我的订单'
}, },
{ {
pagePath: 'pages/peanut/mine', pagePath: 'pages/peanut/mine',
iconPath: 'static/tab/icon4_n.png', iconPath: 'static/tab/tab4.png',
selectedIconPath: 'static/tab/icon4_y.png', selectedIconPath: 'static/tab/tab4.png',
text: '我的' text: '我的'
} }
], ],

View File

@@ -0,0 +1,113 @@
<template>
<!-- 日期显示 -->
<view class="date_box">
<view
v-for="(dateInfo, dateIndex) in dates"
:key="dateIndex"
class="calendar_date__box"
>
<view
class="calendar_date"
:class="{ isSelected: dateActiveIndex === dateIndex && dateInfo.type === 'cur' }"
:style="{
height: cellHeight + 'rpx',
width: cellHeight + 'rpx',
color: swiperMode === 'open' ? dateInfo.type === 'cur' ? '#2C2C2C' : '#959595' : '#2C2C2C',
backgroundColor: dateActiveIndex === dateIndex && dateInfo.type === 'cur' ? dateActiveColor : ''
}"
@tap="chooseDate(dateInfo)"
>
<view class="calendar_date__number">{{ dateInfo.date }}</view>
<view class="calendar_date__isToday" v-if="dateInfo.isToday" :style="{ backgroundColor: dateActiveColor }"></view>
<view class="calendar_date__cricle"></view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
dates: {
type: Array,
default: () => []
},
cellHeight: { // 一列的高度
type: Number,
default: 75
},
dateActiveColor: { // 日期选中颜色
type: String,
default: '#FE6601'
},
selectedDate: {
type: String,
default: ''
},
swiperMode: { // 日历显示模式
type: String,
default: 'open'
},
showActive: { // 是否显示选中高亮日期
type: Boolean,
default: false
}
},
computed: {
dateActiveIndex() {
return this.showActive ? this.dates.map(item => item.dateFormat).indexOf(this.selectedDate) : -1
}
},
methods: {
chooseDate(dateInfo) {
this.$emit('chooseDate', dateInfo)
}
}
}
</script>
<style>
/* 日历轮播 */
.date_box {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.date_box .calendar_date__box {
width: calc(100% / 7);
margin-top: 20rpx;
}
.calendar_date__box .calendar_date {
text-align: center;
margin: 0 auto;
font-weight: bold;
font-size: 28rpx;
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
.calendar_date__box .calendar_date.isSelected {
color: #FFFFFF !important;
}
.calendar_date .calendar_date__isToday {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 50%;
z-index: -1;
opacity: 0.4;
}
.calendar_date .calendar_date__cricle {
width: 9rpx;
height: 9rpx;
border-radius: 50%;
margin-top: 5rpx;
background-color: #FFFFFF;
}
/* 日历轮播 */
</style>

View File

@@ -0,0 +1,68 @@
/**
* 时间格式化
* @param {String} time
* @param {String} cFormat
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
if (!time) return ''
/* 修复IOS系统上面的时间不兼容*/
if (time.toString().indexOf('-') > 0) {
time = time.replace(/-/g, '/')
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
return value.toString().padStart(2, '0')
})
return time_str
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = Object.prototype.toString.call(source) === "[object Array]" ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}

View File

@@ -0,0 +1,641 @@
<template>
<!-- 日历滚动插件 -->
<view class="zsy_calendar">
<!-- 日历顶部信息 -->
<view class="calendar_info">
<text class="title">每日记录</text>
<text class="desc">
({{ getAssignDateInfo(false, 0) === getAssignDateInfo(true, 0) ? '' : getAssignDateInfo(false, 0) + '年' }}{{ getAssignDateInfo(false, 1) }})
</text>
<text v-show="showBackToTodayBtn" class="backToToday" :style="{color: dateActiveColor}" @tap="goToDate()">回到今天</text>
</view>
<!-- 日历周数 -->
<view class="calendar_week">
<view v-for="(item, index) in week" :key="index" class="calendar_week__item">{{ item }}</view>
</view>
<!-- 日历轮播 -->
<view class="calendar_swiper">
<!-- 展开情况下的日历轮播 -->
<swiper
v-if="swiperMode === 'open'"
key="normalSwiper"
circular
:style="{height: swiperHeight('open')}"
:current="current"
:duration="duration"
:skip-hidden-item-layout="true"
@change="e => current = e.detail.current"
>
<swiper-item v-for="(swiper, swiperIndex) in 3" :key="swiperIndex" class="swiper-item">
<DateBox
:dates="calendarSwiperDates[swiperIndex]"
:cellHeight="cellHeight"
:dateActiveColor="dateActiveColor"
:swiperMode="swiperMode"
@chooseDate="chooseDate"
/>
</swiper-item>
</swiper>
<!-- 收缩情况下的日历轮播 -->
<swiper
v-else
key="shrinkSwiper"
circular
:style="{height: swiperHeight('close')}"
:current="shrinkCurrent"
:duration="duration"
:skip-hidden-item-layout="true"
@change="e => shrinkCurrent = e.detail.current"
>
<swiper-item v-for="(swiper, swiperIndex) in 3" :key="swiperIndex" class="swiper-item">
<DateBox
:dates="calendarSwiperShrinkDates[swiperIndex]"
:cellHeight="cellHeight"
:dateActiveColor="dateActiveColor"
:swiperMode="swiperMode"
@chooseDate="chooseShrinkDate"
/>
</swiper-item>
</swiper>
</view>
<!-- 日历切换模式 -->
<view class="calendar_toggle" @tap="swiperMode = swiperMode === 'open' ? 'close' : 'open'">
<view class="icon" :class="{down: swiperMode === 'close'}"></view>
</view>
</view>
</template>
<script>
import { parseTime, deepClone } from './js/utils.js'
import DateBox from './dateBox.vue'
export default {
name: 'ZsyCalendar',
components: {
DateBox
},
props: {
duration: { // 轮播图动画时长
type: Number,
default: 300
},
cellHeight: { // 一列的高度
type: Number,
default: 75
},
dateActiveColor: { // 日期选中颜色
type: String,
default: '#FE6601'
},
sundayIndex: { // 星期天所在索引0表示第一个、6表示最后一个
type: Number,
default: 6
},
mode: { // 日历模式
type: String,
default: 'open'
},
changeSetDefault: { // 月份切换时是否显示一号还是当前月份选中高亮
type: Boolean,
default: true
},
defaultSelectedDate: { // 默认选中日期
type: String | null,
default: null
},
showArrowBtn: { // 是否显示左右切换按钮
type: Boolean,
default: true
}
},
data() {
return {
today: parseTime(new Date(), '{y}-{m}-{d}'), // 今天日期
selectedDate: null, // 选中日期
week: [], // 日历周数
current: 1, // 当前日历轮播默认显示索引
shrinkCurrent: 1, // 缩放日历轮播默认显示索引
calendarSwiperDates: [], // 日历轮播日期信息
calendarSwiperShrinkDates: [], // 日历轮播收缩时的日期信息
dateActive: -1, // 日期选中索引
swiperByClick: false, // 是否通过点击上月份或下月份的日期进行轮播切换
shrinkSwiperByClick: false, // 是否通过点击上月份或下月份的日期进行收缩日历的轮播切换
swiperMode: this.mode, // 日历轮播显示模式 open展开 close收缩
dateCache: {}, // 日期缓存
emitTimer: null, // 日期改变向父级传递当前选中日期计时器
dateClick: false // 是否进行了日期的点击选择
}
},
computed: {
/* 获取指定日期信息
isCurDate: 是否获取当天的信息还是选中日期的信息
index: 0 表示年份 1 表示月份 2 表示日期 */
getAssignDateInfo() {
return (isCurDate, index) => {
return (isCurDate ? this.today : this.selectedDate).split('-')[index] * 1
}
},
// 是否显示回到今天按钮
showBackToTodayBtn() {
return this.getAssignDateInfo(false, 0) !== this.getAssignDateInfo(true, 0) || this.getAssignDateInfo(false, 1) !== this.getAssignDateInfo(true, 1)
},
// 返回轮播图高度
swiperHeight() {
return (swiperMode) => {
const normalHeight = (this.calendarSwiperDates[this.current] || []).length / 7 * (this.cellHeight + 20) + 'rpx'
const shrinkHeight = this.cellHeight + 20 + 'rpx'
return swiperMode === 'open' ? normalHeight : shrinkHeight
}
}
},
watch: {
// 展开日历轮播切换
current(newV, oldV) {
if (newV === 0 && oldV === 2) { // 右滑
this.swiperChange(1)
return
}
if (newV === 2 && oldV === 0) { // 左滑
this.swiperChange(-1)
return
}
if (newV > oldV) { // 右滑
this.swiperChange(1)
} else { // 左滑
this.swiperChange(-1)
}
},
// 收缩日历轮播切换
shrinkCurrent(newV, oldV) {
if (newV === 0 && oldV === 2) { // 右滑
this.shrinkSwiperChange(1)
return
}
if (newV === 2 && oldV === 0) { // 左滑
this.shrinkSwiperChange(-1)
return
}
if (newV > oldV) { // 右滑
this.shrinkSwiperChange(1)
} else { // 左滑
this.shrinkSwiperChange(-1)
}
},
// 日历显示方式切换
swiperMode(newV) {
// 当收缩时初始化收缩轮播图的日期数据
if (newV === 'close') {
this.initCalendarShrinkSwiperDates()
}
},
selectedDate: {
deep: true,
handler(newV, oldV) {
if (newV && (oldV === null || this.dateClick)) { // 初始化/日历点击选择时直接返回
this.emitDate()
this.dateClick = false
} else { // 其它情况做防抖处理
if (this.emitTimer !== null) {
clearTimeout(this.emitTimer)
}
this.emitTimer = setTimeout(() => {
this.emitDate()
}, this.duration + 200)
}
}
}
},
created() {
this.init() // 初始化数据
},
methods: {
// 初始化数据
init() {
if (this.selectedDate === null) { // 默认选中日期为当天
this.selectedDate = this.defaultSelectedDate || this.today
}
this.initWeek() // 初始化要显示的周数
this.initCalendarSwiperDates() // 初始化日历轮播日期信息
// 解决swiperMode初始化为收缩时没有初始化日历收缩轮播日期信息
if (this.swiperMode === 'close') {
this.initCalendarShrinkSwiperDates()
}
},
// 初始化周数
initWeek() {
const normalWeek = ['日', '一', '二', '三', '四', '五', '六'] // 正常周数
const sIndex = this.sundayIndex < 0 ? 0 : this.sundayIndex >= normalWeek.length ? normalWeek.length - 1 : this.sundayIndex
normalWeek.unshift(...normalWeek.slice(-sIndex))
normalWeek.length = 7
this.week = normalWeek
},
// 初始化展开时的日历轮播日期信息
initCalendarSwiperDates(cb) {
const year = this.getAssignDateInfo(false, 0)
const month = this.getAssignDateInfo(false, 1)
const cur = this.generateCalendar(year, month)
const prev = this.generateCalendar(month === 1 ? year - 1 : year, month === 1 ? 12 : month - 1)
const next = this.generateCalendar(month === 12 ? year + 1 : year, month === 12 ? 1 : month + 1)
// 根据current来判断相邻的轮播存放哪些日历数据
if (this.current === 0) {
this.calendarSwiperDates = [cur, next, prev]
} else if (this.current === 1) {
this.calendarSwiperDates = [prev, cur, next]
} else if (this.current === 2) {
this.calendarSwiperDates = [next, prev, cur]
}
this.swiperByClick = false
// 初始化日期信息完毕执行回调函数
cb && cb()
},
// 生成展开的日历数据
generateCalendar(year, month) {
let calendarDate = []
// 先获取缓存里面有没有该月的日期数据
if (this.dateCache[`${year}-${month}`]) {
calendarDate = deepClone(this.dateCache[`${year}-${month}`])
} else { // 进行月份日期的计算
const monthDates = new Date(year, month, 0).getDate() // 获取此月份总天数
const normalWeek = ['一', '二', '三', '四', '五', '六', '日'] // 正常周数
const monthFirstDay = normalWeek[new Date(year, month - 1, 0).getDay()] // 获取本月一号为星期几
const monthFirstDayIndex = this.week.indexOf(monthFirstDay) // 计算本月一号在日历周数中的索引,索引之前的填充上个月的后几天
// 本月一号在日历中不是第一个位置,需要进行填充
if (monthFirstDayIndex !== 0) {
const prevMonthDates = new Date(year, month - 1, 0).getDate() // 获取上一个月份的总天数
// 填充本月一号之前的数据
for (let i = 0; i < monthFirstDayIndex; i ++) {
const item = {
year: month === 1 ? year - 1 : year,
month: month === 1 ? 12 : month - 1,
date: prevMonthDates - i,
type: 'prev'
}
// 判断填充的日期是否包含今天日期
this.theDateIsToday(item)
calendarDate.unshift(item)
}
}
// 循环生成当月所有日期
for (let i = 1; i <= monthDates; i ++) {
const item = {
year,
month,
date: i,
isSelected: false,
isToday: false,
type: 'cur'
}
// 今天的日期在不在里面
this.theDateIsToday(item)
calendarDate.push(item)
}
const residue = calendarDate.length % 7
// 判断是否需要填充下个月的前几天
if (residue !== 0) {
for (let i = 1; i <= 7 - residue; i ++) {
const item = {
year: month === 12 ? year + 1 : year,
month: month === 12 ? 1 : month + 1,
date: i,
type: 'next'
}
// 下个月的前几天包含今天
this.theDateIsToday(item)
calendarDate.push(item)
}
}
this.dateCache[`${year}-${month}`] = deepClone(calendarDate)
}
// 进行日期的默认选中
if (year === this.getAssignDateInfo(false, 0) && month === this.getAssignDateInfo(false, 1)) {
for (let i = 0, len = calendarDate.length; i < len; i++) {
if (calendarDate[i].type === 'cur' && calendarDate[i].date === this.getAssignDateInfo(false, 2)) {
calendarDate[i].isSelected = true
this.dateActive = i
break
}
}
}
return calendarDate
},
// 判断日期是否为今天
theDateIsToday(item) {
if (item.year + '-' + item.month + '-' + item.date === this.getAssignDateInfo(true, 0) + '-' + this.getAssignDateInfo(true, 1) + '-' + this.getAssignDateInfo(true, 2)) {
item.isToday = true
}
},
// 初始化收缩时的日历轮播日期信息
initCalendarShrinkSwiperDates(swiperChangeType) {
let line = null
/**
* 日历收缩事件/当前滑动不涉及到到上个/下个月的日期数据
* 日历滑动到上一周并且本周不属于第一行并且上一周选中的日期必须是本月份里面的日期
* 日历滑动到下一周且本周不属于最后一行
*/
const curDateLine = Math.floor(this.dateActive / 7)
if (!swiperChangeType ||
(swiperChangeType === -1 && curDateLine !== 0 && this.calendarSwiperDates[this.current][(curDateLine - 1) * 7].type === 'cur') ||
(swiperChangeType === 1 && curDateLine + 1 !== this.calendarSwiperDates[this.current].length / 7)
) {
// 计算当前周选中日期处于日历中的哪一行位置
const curCalendarSwiperDates = this.calendarSwiperDates[this.current]
line = Math.floor(curCalendarSwiperDates.map(item => item.type === 'cur' ? item.date : -1).indexOf(this.getAssignDateInfo(false, 2)) / 7)
// 收缩日历滑动事件需要进行日期的选中处理
if (swiperChangeType) {
// 将当前选中日期清除选中状态
this.calendarSwiperDates[this.current][this.dateActive].isSelected = false
// 重新计算日期选中高亮并把下一个日期进行选中
this.dateActive = line * 7
this.calendarSwiperDates[this.current][this.dateActive].isSelected = true
}
} else { // 收缩日历滑动事件
// 将当前选中日期清除选中状态
this.calendarSwiperDates[this.current][this.dateActive].isSelected = false
// 涉及了上个月/下个月的日期数据,需要重新计算展开日历轮播的日期数据
let currentNum = this.current + swiperChangeType
currentNum = currentNum > 2 ? 0 : currentNum < 0 ? 2 : currentNum
this.current = currentNum
// 计算上一周/下一周选中日期处于日历中的哪一行位置
const curCalendarSwiperDates = this.calendarSwiperDates[this.current]
line = Math.floor(curCalendarSwiperDates.map(item => item.type === 'cur' ? item.date : -1).indexOf(this.getAssignDateInfo(false, 2)) / 7)
// 重新计算日期选中高亮并把下一个日期进行选中
this.dateActive = line * 7
this.calendarSwiperDates[this.current][this.dateActive].isSelected = true
}
const cur = this.generateShrinkCalendar(0, line)
const prev = this.generateShrinkCalendar(-1, line)
const next = this.generateShrinkCalendar(1, line)
// 根据shrinkCurrent来判断相邻的轮播存放哪些日历数据
if (this.shrinkCurrent === 0) {
this.calendarSwiperShrinkDates = [cur, next, prev]
} else if (this.shrinkCurrent === 1) {
this.calendarSwiperShrinkDates = [prev, cur, next]
} else if (this.shrinkCurrent === 2) {
this.calendarSwiperShrinkDates = [next, prev, cur]
}
},
// 生成收缩的日历数据
generateShrinkCalendar(type, line) {
// 返回当前这一周的日期数据
if (type === 0) {
return this.calendarSwiperDates[this.current].slice(line * 7, (line + 1) * 7)
}
// 返回上一周的日期数据
if (type === -1) {
// 当前选中的日期是否位于第一行
if (line === 0) {
/**
* 当前日历的第一行是否包含有上个月的日期
* 如果有包含,则返回上个月的倒数第二行日期
* 如果没有包含,则返回上个月的倒数第一行日期
*/
// 计算上个月的索引值
const prevIndex = this.current === 0 ? 2 : this.current - 1
// 获取上个月的日期数据
const prevCalendarSwiperDates = this.calendarSwiperDates[prevIndex]
// 获取上个月的日历行数
const prevCalendarSwiperDatesLine = prevCalendarSwiperDates.length / 7
if (this.calendarSwiperDates[this.current][0].type === 'prev') { // 倒数第二行
return prevCalendarSwiperDates.slice((prevCalendarSwiperDatesLine - 2) * 7, (prevCalendarSwiperDatesLine - 1) * 7)
} else { // 倒数第一行
return prevCalendarSwiperDates.slice((prevCalendarSwiperDatesLine - 1) * 7)
}
} else {
return this.calendarSwiperDates[this.current].slice((line - 1) * 7, line * 7)
}
}
// 返回下一周的日期数据
if (type === 1) {
// 计算当前日历月份总共有多少行
const curMonthMaxLine = this.calendarSwiperDates[this.current].length / 7
// 当前选中的日期是否位于最后一行
if (line === curMonthMaxLine - 1) {
/**
* 当前日历的最后一行是否包含有下个月的日期
* 如果有包含,则返回下个月的第二行日期
* 如果没有包含,则返回上个月的第一行日期
*/
// 计算下个月的索引值
const nextIndex = this.current === 2 ? 0 : this.current + 1
// 获取下个月的日期数据
const nextCalendarSwiperDates = this.calendarSwiperDates[nextIndex]
// 获取下个月的日历行数
const nextCalendarSwiperDatesLine = nextCalendarSwiperDates.length / 7
if (this.calendarSwiperDates[this.current][this.calendarSwiperDates[this.current].length - 1].type === 'next') { // 第二行
return nextCalendarSwiperDates.slice(7, 14)
} else { // 第一行
return nextCalendarSwiperDates.slice(0, 7)
}
} else {
return this.calendarSwiperDates[this.current].slice((line + 1) * 7, (line + 2) * 7)
}
}
},
// 展开日历轮播切换事件
swiperChange(type) {
// 通过点击上个月/下个月日期进行切换,不需要默认选中下个月的一号,直接选中点击的那个日期
if (!this.swiperByClick && this.swiperMode === 'open') {
this.getPrevOrNextDate(type)
}
setTimeout(() => { // 设置定时器是为了防止轮播切换时生成数据造成页面卡顿
this.initCalendarSwiperDates(() => {
this.swiperMode === 'close' && this.initCalendarShrinkSwiperDates()
}) // 初始化日历轮播日期信息
}, this.swiperMode === 'open' ? this.duration : 0)
},
// 收缩日历轮播切换事件
shrinkSwiperChange(type) {
// 默认选中下个星期的开始日期
this.getPrevOrNextStartDate(type)
setTimeout(() => { // 设置定时器是为了防止轮播切换时生成数据造成页面卡顿
this.initCalendarShrinkSwiperDates(type) // 初始化日历轮播日期信息
}, this.duration)
},
// 手动切换日历
switchCalendar(type) {
const currentKey = this.swiperMode === 'close' ? 'shrinkCurrent' : 'current'
const v = this[currentKey] + (type === 'prev' ? -1 : 1)
this[currentKey] = v === -1 ? 2 : v === 3 ? 0 : v
},
// 获取上一个月/下一个月的一号日期
getPrevOrNextDate(type) {
const year = this.getAssignDateInfo(false, 0)
let month = this.getAssignDateInfo(false, 1)
month = month + type
// 判断切换月份时选中当前日期高亮还是一号,若选中当前日期高亮需进行大小判断
const curActiveDate = this.getAssignDateInfo(false, 2)
const maxDate = new Date(year, month, 0).getDate()
const date = this.changeSetDefault ? 1 : curActiveDate > maxDate ? maxDate : curActiveDate
this.selectedDate = parseTime(new Date(year, month - 1, date), '{y}-{m}-{d}')
},
// 获取上个星期/下一星期的开始日期
getPrevOrNextStartDate(type) {
const date = this.calendarSwiperShrinkDates[this.shrinkCurrent][0]
this.selectedDate = parseTime(new Date(date.year, date.month - 1, date.date), '{y}-{m}-{d}')
},
// 前往某一天 格式 YYYY-MM | YYYY-MM-DD
goToDate(date = this.today) {
try {
if (date.split('-').length < 2 || date.split('-').length > 3) throw '参数有误'
if (date.split('-').length === 2) {
date += '-01'
}
} catch (err) {
throw Error('请检查参数是否符合规范')
}
this.selectedDate = date
this.initCalendarSwiperDates(() => {
this.initCalendarShrinkSwiperDates()
})
},
// 日历轮播展开的情况下选择日期
chooseDate(dateInfo, dateIndex) {
// 重复点击后续不做处理
if (dateInfo.isSelected) return false
// 是否点击了上个月份的后几天或者点击了下个月份的前几天
if (dateInfo.type !== 'cur') {
if (dateInfo.type === 'prev') { // 点击了上个月份的后几天,滑到上个月
this.current = this.current === 0 ? 2 : this.current - 1
} else { // 点击了下个月份的前几天,滑到下个月
this.current = this.current === 2 ? 0 : this.current + 1
}
// 将选中日期赋值为当前点击的那个日期
this.selectedDate = parseTime(new Date(dateInfo.year, dateInfo.month - 1, dateInfo.date), '{y}-{m}-{d}')
this.swiperByClick = true
return false
}
// 将当前选中的日期清空并选中最新的日期
this.calendarSwiperDates[this.current][this.dateActive].isSelected = false
this.dateActive = dateIndex
const date = this.calendarSwiperDates[this.current][this.dateActive]
date.isSelected = true
this.selectedDate = parseTime(new Date(date.year, date.month - 1, date.date), '{y}-{m}-{d}')
this.dateClick = true
},
// 日历轮播收缩的情况下选择日期
chooseShrinkDate(dateInfo, dateIndex) {
// 重复点击后续不做处理
if (dateInfo.isSelected) return false
this.dateClick = true
// 是否点击了上个月份的后几天或者点击了下个月份的前几天
if (dateInfo.type !== 'cur') {
if (dateInfo.type === 'prev') { // 点击了上个月份的后几天,切换到上个月
this.current = this.current === 0 ? 2 : this.current - 1
} else { // 点击了下个月份的前几天,切换到下个月
this.current = this.current === 2 ? 0 : this.current + 1
}
this.dateActive = dateIndex
// 将选中日期赋值为当前点击的那个日期
this.selectedDate = parseTime(new Date(dateInfo.year, dateInfo.month - 1, dateInfo.date), '{y}-{m}-{d}')
return false
}
// 计算当前选中日期之前有多少个日期
const dateActiveLine = Math.floor(this.dateActive / 7) * 7
// 将当前选中的日期清空并选中最新的日期
this.calendarSwiperDates[this.current][this.dateActive].isSelected = false
this.dateActive = dateIndex + dateActiveLine
const date = this.calendarSwiperDates[this.current][this.dateActive]
date.isSelected = true
this.selectedDate = parseTime(new Date(date.year, date.month - 1, date.date), '{y}-{m}-{d}')
},
// 向父组件传递当前选中数据
emitDate() {
const { year, month, date } = this.calendarSwiperDates[this.current][this.dateActive]
const e = {
selectedDate: this.selectedDate,
year,
month,
date
}
this.$emit('change', e)
}
}
}
</script>
<style>
.zsy_calendar {
width: 100%;
padding: 20rpx 0;
box-sizing: border-box;
background-color: #fff;
border-radius: 20rpx;
}
/* 日历顶部信息 */
.calendar_info {
display: flex;
align-items: center;
padding: 0 20rpx;
}
.calendar_info .title {
font-size: 34rpx;
font-weight: bold;
color: #2C2C2C;
}
.calendar_info .desc {
margin-left: 29rpx;
font-size: 28rpx;
color: #959595;
}
.calendar_info .backToToday {
margin-left: auto;
font-size: 24rpx;
}
/* 日历顶部信息 */
/* 日历周数 */
.calendar_week {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 26rpx;
color: #959595;
margin: 20rpx 0rpx;
}
.calendar_week .calendar_week__item {
width: calc(100% / 7);
text-align: center;
}
/* 日历周数 */
/* 日历切换模式 */
.calendar_toggle {
position: relative;
padding: 10rpx 0;
margin: 10rpx 20rpx 0;
display: flex;
justify-content: center;
}
.calendar_toggle .icon {
width: 30rpx;
height: 30rpx;
background-image: url('../../static/zsy-calendar/arrow.png');
background-size: contain;
background-repeat: no-repeat;
margin: 0 auto;
transition: all .3s;
}
.icon.down {
transform: rotate(180deg);
}
.calendar_toggle::before, .calendar_toggle::after {
width: calc(50% - 30rpx);
border-top: solid 2rpx #EAEAEA;
content: '';
display: block;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.calendar_toggle::before {
left: 0;
}
.calendar_toggle::after {
right: 0;
}
/* 日历切换模式 */
</style>

View File

@@ -0,0 +1,536 @@
<template>
<!-- 日历滚动插件 -->
<view class="zsy_calendar">
<!-- 日历顶部信息 -->
<view class="calendar_info" >
<view class="">
<text class="title">读书打卡</text>
<text class="desc">
({{ getAssignDateInfo(false, 0) === getAssignDateInfo(true, 0) ? '' : getAssignDateInfo(false, 0) + '年' }}{{ getAssignDateInfo(false, 1) }})
</text>
</view>
<view class="dakaBtn" @tap="goToDate()">
<u-icon name="checkbox-mark" color="#55aa7f" size="24" style="display: inline;"></u-icon>
<text>打卡</text>
</view>
<!-- <text v-show="showBackToTodayBtn" class="backToToday" :style="{color: dateActiveColor}" @tap="goToDate()">回到今天</text> -->
</view>
<!-- 日历周数 -->
<view class="calendar_week">
<view v-for="(item, index) in week" :key="index" class="calendar_week__item">{{ item }}</view>
</view>
<!-- 日历轮播 -->
<view class="calendar_swiper">
<swiper
key="normalSwiper"
circular
:style="{height: swiperHeight}"
:current="current"
:duration="duration"
:skip-hidden-item-layout="true"
@change="e => current = e.detail.current"
>
<swiper-item v-for="(swiper, swiperIndex) in 3" :key="swiperIndex" class="swiper-item">
<DateBox
:dates="getcurCalendarDates[swiperIndex]"
:cellHeight="cellHeight"
:selectedDate="selectedDate"
:dateActiveColor="dateActiveColor"
:swiperMode="swiperMode"
:showActive="emitTimer === null"
@chooseDate="chooseDate"
/>
</swiper-item>
</swiper>
</view>
<!-- 日历切换模式 -->
<view class="calendar_toggle" @tap="swiperMode = swiperMode === 'open' ? 'close' : 'open'">
<view class="icon" :class="{down: swiperMode === 'close'}"></view>
</view>
</view>
</template>
<script>
import { parseTime, deepClone } from './js/utils.js'
import DateBox from './dateBox.vue'
export default {
name: 'ZsyCalendar',
components: {
DateBox
},
props: {
duration: { // 轮播图动画时长
type: Number,
default: 300
},
cellHeight: { // 一列的高度
type: Number,
default: 75
},
dateActiveColor: { // 日期选中颜色
type: String,
default: '#FE6601'
},
sundayIndex: { // 星期天所在索引0表示第一个、6表示最后一个
type: Number,
default: 6
},
mode: { // 日历模式
type: String,
default: 'close'
},
changeSetDefault: { // 月份切换时是否显示一号还是当前月份选中高亮
type: Boolean,
default: true
},
defaultSelectedDate: { // 默认选中日期
type: String | null,
default: null
},
showArrowBtn: { // 是否显示左右切换按钮
type: Boolean,
default: true
}
},
data() {
return {
today: parseTime(new Date(), '{y}-{m}-{d}'), // 今天日期
selectedDate: null, // 选中日期
week: [], // 日历周数
current: 1, // 当前日历轮播默认显示索引
calendarSwiperDates: [], // 日历轮播日期信息
swiperChangeByClick: false, // 是否通过点击上月份或下月份的日期进行轮播切换
swiperMode: this.mode, // 日历轮播显示模式 open展开 close收缩
monthDateCache: {}, // 月份日期缓存数据
emitTimer: null, // 日期改变向父级传递当前选中日期计时器
dateClick: false // 是否进行了日期的点击选择
}
},
computed: {
// 返回当前日期信息(展开状态下为每月,收缩状态下为每周)
getcurCalendarDates() {
if (this.swiperMode === 'open') { // 展开
return this.calendarSwiperDates
} else {
return this.getCalendarShrinkSwiperDates()
}
},
// 计算选中日期的上月、本月、下月的年月信息
getAdjacentYMD() {
const year = this.getAssignDateInfo(false, 0)
const month = this.getAssignDateInfo(false, 1)
const prev = `${month === 1 ? year - 1 : year}-${month === 1 ? 12 : month - 1}`
const cur = `${year}-${month}`
const next = `${month === 12 ? year + 1 : year}-${month === 12 ? 1 : month + 1}`
return [prev, cur, next]
},
/* 获取指定日期信息
isToday: 是否获取当天的信息还是选中日期的信息
index: 0 表示年份 1 表示月份 2 表示日期 */
getAssignDateInfo() {
return (isToday, index) => {
return (isToday ? this.today : this.selectedDate).split('-')[index] * 1
}
},
// 是否显示回到今天按钮
showBackToTodayBtn() {
return this.getAssignDateInfo(false, 0) !== this.getAssignDateInfo(true, 0) || this.getAssignDateInfo(false, 1) !== this.getAssignDateInfo(true, 1)
},
// 返回轮播图高度
swiperHeight() {
const normalHeight = (this.calendarSwiperDates[this.current] || []).length / 7 * (this.cellHeight + 20) + 'rpx'
const shrinkHeight = this.cellHeight + 20 + 'rpx'
return this.swiperMode === 'open' ? normalHeight : shrinkHeight
}
},
watch: {
// 展开日历轮播切换
current(newV, oldV) {
if (newV === 0 && oldV === 2) { // 右滑
this.swiperChange(1)
return
}
if (newV === 2 && oldV === 0) { // 左滑
this.swiperChange(-1)
return
}
if (newV > oldV) { // 右滑
this.swiperChange(1)
} else { // 左滑
this.swiperChange(-1)
}
},
selectedDate: {
deep: true,
handler(newV, oldV) {
var selectD = new Date(newV).getTime();
var curTime = new Date().getTime();
//console.log(newV)
console.log(curTime,selectD)
if(selectD > curTime){
uni.showToast({
title:'未来日期不可打卡',
icon:'none'
})
return false
}else{
// 判断月历日期数据需不需要改变
if (this.swiperMode === 'close') {
setTimeout(() => {
this.generateAdjacentMonthDate() // 生成临近月份日期缓存数据
}, this.duration);
}
if (newV && (oldV === null || this.dateClick)) { // 初始化/日历点击选择时直接返回
this.emitDate()
this.dateClick = false
} else { // 其它情况做防抖处理
if (this.emitTimer !== null) {
clearTimeout(this.emitTimer)
this.emitTimer = null
}
this.emitTimer = setTimeout(() => {
this.emitDate()
this.emitTimer = null
}, this.duration + 200)
}
}}
}
},
created() {
this.init() // 初始化数据
},
methods: {
// 初始化数据
init() {
if (this.selectedDate === null) { // 默认选中日期为当天
this.selectedDate = this.defaultSelectedDate || this.today
}
this.initWeek() // 初始化要显示的周数
this.generateAdjacentMonthDate() // 生成临近月份日期缓存数据
},
// 初始化周数
initWeek() {
const normalWeek = ['日', '一', '二', '三', '四', '五', '六'] // 正常周数
const sIndex = this.sundayIndex < 0 ? 0 : this.sundayIndex >= normalWeek.length ? normalWeek.length - 1 : this.sundayIndex
normalWeek.unshift(...normalWeek.slice(-sIndex))
normalWeek.length = 7
this.week = normalWeek
},
// 根据current自动对轮播数据进行衔接排序
adjacentSortByCurrent(prev, cur, next) {
let arr
if (this.current === 0) {
arr = [cur, next, prev]
} else if (this.current === 1) {
arr = [prev, cur, next]
} else if (this.current === 2) {
arr = [next, prev, cur]
}
console.log(arr,'arr')
return arr
},
// 生成本月、上个月、下个月日期信息
generateAdjacentMonthDate() {
const arr = []
this.getAdjacentYMD.map(YM => {
const [year, month] = YM.split('-')
arr.push(this.generateMonthDateCache(year, month))
})
console.log(arr,'arr')
const [prev, cur, next] = arr
this.calendarSwiperDates = this.adjacentSortByCurrent(prev, cur, next)
if (this.swiperChangeByClick) {
this.swiperChangeByClick = false
}
},
// 生成月份日期缓存数据并返回
generateMonthDateCache(year, month) {
year = Number(year)
month = Number(month)
// 缓存中已存在
if (this.monthDateCache[`${year}-${month}`]) return this.monthDateCache[`${year}-${month}`]
let calendarDate = []
const monthDates = new Date(year, month, 0).getDate() // 获取此月份总天数
const normalWeek = ['一', '二', '三', '四', '五', '六', '日'] // 正常周数
const monthFirstDay = normalWeek[new Date(year, month - 1, 0).getDay()] // 获取本月一号为星期几
const monthFirstDayIndex = this.week.indexOf(monthFirstDay) // 计算本月一号在日历周数中的索引,索引之前的填充上个月的后几天
// 本月一号在日历中不是第一个位置,需要进行填充
if (monthFirstDayIndex !== 0) {
const prevMonthDates = new Date(year, month - 1, 0).getDate() // 获取上一个月份的总天数
// 填充本月一号之前的数据
for (let i = 0; i < monthFirstDayIndex; i ++) {
const item = {
year: month === 1 ? year - 1 : year,
month: month === 1 ? 12 : month - 1,
date: prevMonthDates - i,
dateFormat: `${month === 1 ? year - 1 : year}-${String(month === 1 ? 12 : month - 1).padStart(2, '0')}-${String(prevMonthDates - i).padStart(2, '0')}`,
type: 'prev'
}
// 判断填充的日期是否包含今天日期
this.theDateIsToday(item)
calendarDate.unshift(item)
}
}
// 循环生成当月所有日期
for (let i = 1; i <= monthDates; i ++) {
const item = {
year,
month,
date: i,
isSelected: false,
dateFormat: `${year}-${String(month).padStart(2, '0')}-${String(i).padStart(2, '0')}`,
type: 'cur'
}
// 今天的日期在不在里面
this.theDateIsToday(item)
calendarDate.push(item)
}
const residue = calendarDate.length % 7
// 判断是否需要填充下个月的前几天
if (residue !== 0) {
for (let i = 1; i <= 7 - residue; i ++) {
const item = {
year: month === 12 ? year + 1 : year,
month: month === 12 ? 1 : month + 1,
date: i,
dateFormat: `${month === 12 ? year + 1 : year}-${String(month === 12 ? 1 : month + 1).padStart(2, '0')}-${String(i).padStart(2, '0')}`,
type: 'next'
}
// 下个月的前几天包含今天
this.theDateIsToday(item)
calendarDate.push(item)
}
}
this.monthDateCache[`${year}-${month}`] = deepClone(calendarDate)
return this.monthDateCache[`${year}-${month}`]
},
// 轮播图切换结束
swiperChange(e) {
// 切换上个月/下个月,默认选中一号 / 切换上一周/下一周,默认选中第一天
if (!this.swiperChangeByClick) {
this.getPrevOrNextDate(e)
}
if (this.swiperMode === 'open') { // 展开
// 通过点击上个月/下个月日期进行切换,不需要默认选中下个月的一号,直接选中点击的那个日期
setTimeout(() => {
this.generateAdjacentMonthDate() // // 重新生成临近月份日期缓存数据
}, this.duration)
}
},
// 判断日期是否为今天
theDateIsToday(item) {
if (`${item.year}${item.month}${item.date}` === `${this.getAssignDateInfo(true, 0)}${this.getAssignDateInfo(true, 1)}${this.getAssignDateInfo(true, 2)}`) {
item.isToday = true
}
},
// 计算收缩时的日历轮播日期信息
getCalendarShrinkSwiperDates() {
const [prevYM, curYM, nextYM] = this.getAdjacentYMD
// 本月日期数据
const curDates = this.monthDateCache[curYM]
// 计算当前日期所在行
const line = Math.floor(curDates.map(item => item.dateFormat).indexOf(this.selectedDate) / 7)
// 当前周日期信息
const cur = curDates.slice(line * 7, (line + 1) * 7)
let prev, next
/**
* 获取上一周日期信息
* 注意:当选中日期为第一周要额外判断,如果刚好为日历的第一天,则上一周数据应为上一个月的最后一周,否则为上一个月的倒数第二周
*/
if (line === 0) {
// 获取上个月日历数据
const prevDates = this.monthDateCache[prevYM]
// 获取上个月的日历行数
const prevDatesLine = prevDates.length / 7
if (curDates[0].dateFormat === this.selectedDate) { // 选中日期刚好为日历第一天
prev = prevDates.slice((prevDatesLine - 1) * 7) // 上个月倒数第一周数据
} else {
prev = prevDates.slice((prevDatesLine - 2) * 7, (prevDatesLine - 1) * 7) // 上个月倒数第二周数据
}
} else {
prev = curDates.slice((line - 1) * 7, line * 7)
}
/**
* 获取下一周日期信息
* 注意:当选中日期为最后一周要额外判断,如果刚好为日历的最后一天,则下一周数据应为下一个月的第一周,否则为下一个月的第二周
*/
if (line + 1 === curDates.length / 7) {
// 获取下个月的日期数据
const nextDates = this.monthDateCache[nextYM]
if (curDates[curDates.length - 1].dateFormat === this.selectedDate) { // 选中日期刚好为日历最后一天
next = nextDates.slice(0, 7) // 下个月第一周数据
} else {
next = nextDates.slice(7, 14) // 下个月第二周数据
}
} else {
next = curDates.slice((line + 1) * 7, (line + 2) * 7)
}
return this.adjacentSortByCurrent(prev, cur, next)
},
// 手动切换日历
switchCalendar(type) {
const currentKey = this.swiperMode === 'close' ? 'shrinkCurrent' : 'current'
const v = this[currentKey] + (type === 'prev' ? -1 : 1)
this[currentKey] = v === -1 ? 2 : v === 3 ? 0 : v
},
// 获取月的一号日期/周的第一天
getPrevOrNextDate(type) {
if (this.swiperMode === 'open') {
const year = this.getAssignDateInfo(false, 0)
let month = this.getAssignDateInfo(false, 1)
month = month + type
// 判断切换月份时选中当前日期高亮还是一号,若选中当前日期高亮需进行大小判断
const curActiveDate = this.getAssignDateInfo(false, 2)
const maxDate = new Date(year, month, 0).getDate()
const date = this.changeSetDefault ? 1 : curActiveDate > maxDate ? maxDate : curActiveDate
this.selectedDate = parseTime(new Date(year, month - 1, date), '{y}-{m}-{d}')
} else {
let current = this.current + type < 0 ? 2 : this.current + type > 2 ? 0 : this.current + type
this.selectedDate = this.getcurCalendarDates[current][0].dateFormat
}
},
// 前往某一天 格式 YYYY-MM | YYYY-MM-DD
goToDate(date = this.today) {
try {
if (date.split('-').length < 2 || date.split('-').length > 3) throw '参数有误'
if (date.split('-').length === 2) {
date += '-01'
}
} catch (err) {
throw Error('请检查参数是否符合规范')
}
this.selectedDate = date
this.generateAdjacentMonthDate()
},
// 日历轮播展开的情况下选择日期
chooseDate(dateInfo) {
// 重复点击后续不做处理
if (dateInfo.dateFormat === this.selectedDate) return false
if (this.swiperMode === 'open') { // 展开
// 是否点击了上个月份的后几天或者点击了下个月份的前几天
if (dateInfo.type !== 'cur') {
if (dateInfo.type === 'prev') { // 点击了上个月份的后几天,滑到上个月
this.current = this.current === 0 ? 2 : this.current - 1
} else { // 点击了下个月份的前几天,滑到下个月
this.current = this.current === 2 ? 0 : this.current + 1
}
// 将选中日期赋值为当前点击的那个日期
this.swiperChangeByClick = true
} else {
this.dateClick = true
}
} else { // 收缩
// 是否点击了上个月份的后几天或者点击了下个月份的前几天
if (dateInfo.type !== 'cur') {
// 将选中日期赋值为当前点击的那个日期
this.swiperChangeByClick = true
}
this.dateClick = true
}
// 将当前选中的日期清空并选中最新的日期
this.selectedDate = dateInfo.dateFormat
},
// 向父组件传递当前选中数据
emitDate() {
const e = {
selectedDate: this.selectedDate
}
this.$emit('change', e)
}
}
}
</script>
<style>
.zsy_calendar {
width: 100%;
padding: 20rpx 0;
box-sizing: border-box;
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
}
.dakaBtn{
color: #55aa7f; display: flex; padding: 3rpx 5rpx; border: #55aa7f 1px solid; border-radius: 10rpx;
}
/* 日历顶部信息 */
.calendar_info {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20rpx;
}
.calendar_info .title {
font-size: 34rpx;
font-weight: bold;
color: #2C2C2C;
}
.calendar_info .desc {
margin-left: 29rpx;
font-size: 28rpx;
color: #959595;
}
.calendar_info .backToToday {
margin-left: auto;
font-size: 24rpx;
}
/* 日历顶部信息 */
/* 日历周数 */
.calendar_week {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 26rpx;
color: #959595;
margin: 20rpx 0rpx;
}
.calendar_week .calendar_week__item {
width: calc(100% / 7);
text-align: center;
}
/* 日历周数 */
/* 日历切换模式 */
.calendar_toggle {
position: relative;
padding: 10rpx 0;
margin: 10rpx 20rpx 0;
display: flex;
justify-content: center;
}
.calendar_toggle .icon {
width: 30rpx;
height: 30rpx;
background-image: url('../../static/zsy-calendar/arrow.png');
background-size: contain;
background-repeat: no-repeat;
margin: 0 auto;
transform: rotate(0deg);
transition: all .3s;
}
.icon.down {
transform: rotate(180deg);
}
.calendar_toggle::before, .calendar_toggle::after {
width: calc(50% - 30rpx);
border-top: solid 2rpx #EAEAEA;
content: '';
display: block;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.calendar_toggle::before {
left: 0;
}
.calendar_toggle::after {
right: 0;
}
/* 日历切换模式 */
</style>

View File

@@ -86,7 +86,7 @@
bgiStyle: { bgiStyle: {
background: '#2ab58833' background: '#2ab58833'
}, },
iconStyle: { iconStyle: {
fontSize: '40rpx', fontSize: '40rpx',
fontWeight: 'bold', fontWeight: 'bold',
color: '#54a966', color: '#54a966',

View File

@@ -29,8 +29,10 @@
<view v-if="contentShow == 0"> <view v-if="contentShow == 0">
<view class="tingshuList" v-if="listenList.length > 0"> <view class="tingshuList" v-if="listenList.length > 0">
<h4>赠送听书权益</h4> <h4>赠送听书权益</h4>
<view class="item flexbox" v-for="item in listenList" :key="item.id" @click="goToListen(item.id)"> <view class="item flexbox" v-for="item in listenList" :key="item.id" style="vertical-align: middle;">
<text>{{item.name}}</text><u-icon name="volume" color="#71d5a1" size="24">立即试听</u-icon> <text style="margin-top: 10rpx; padding-right: 10rpx;">{{item.name}}</text>
<u-icon v-if="item.canListen == 'true'" name="volume" color="#71d5a1" size="24" @click="goToListen(item.id)"></u-icon>
<u-icon v-else name="volume" color="#71d5a1" size="24" @click="goToListenNone(item.id)"></u-icon>
</view> </view>
</view> </view>
<view class="bookInfo" > <view class="bookInfo" >
@@ -294,6 +296,12 @@
this.goPurse() this.goPurse()
} }
}, },
goToListenNone(){
uni.showToast({
title:'该书暂未生成音频内容,敬请期待!',
icon:'none'
})
},
// 加入购物车 // 加入购物车
addCart() { addCart() {
if (this.productInfo.productStock == 0) { if (this.productInfo.productStock == 0) {
@@ -466,7 +474,7 @@ formatRichText (html) { //控制小程序中图片大小
.tingshuList{margin-top: 20rpx; background-color: #fff; padding: 20rpx; .tingshuList{margin-top: 20rpx; background-color: #fff; padding: 20rpx;
border-radius: 20rpx; margin-bottom: 20rpx; padding-top: 40rpx; border-radius: 20rpx; margin-bottom: 20rpx; padding-top: 40rpx;
background-image: linear-gradient(0deg, #f7fffc 0%, #def0ea 100%); background-image: linear-gradient(0deg, #f7fffc 0%, #def0ea 100%);
.item{margin-bottom: 20rpx;} .item{margin-bottom: 20rpx; vertical-align: middle; }
h4{color: #5fb386; font-size: 40rpx; margin-bottom: 20rpx;} h4{color: #5fb386; font-size: 40rpx; margin-bottom: 20rpx;}
text{color: #444; font-size: 32rpx; padding-left: 20rpx;} text{color: #444; font-size: 32rpx; padding-left: 20rpx;}
} }

View File

@@ -49,14 +49,13 @@
</view> </view>
<br clear="both"> <br clear="both">
</view> </view>
<!-- <view class="orderOper" v-if="orderContet.orderStatus=='3'"> -->
<view class="orderOper" > <view class="orderOper" >
<view style="width: 100%; text-align: right;"> <view style="width: 100%; text-align: right;">
<view @click.stop="pingji(item.productId)" class="opCan" >评价</view> <view v-if="userRecordid == null" @click.stop="pingji(item.productId)" class="opCan" >评价</view>
<view @click.stop="showZhuiping(item.productId)" class="opCan" >追评</view> <view v-else @click.stop="showZhuiping(item.productId)" class="opCan" >追评</view>
</view> </view>
</view> </view>
<br clear="both"> <br clear="both">
</view> </view>
@@ -183,6 +182,7 @@
export default { export default {
data() { data() {
return { return {
userRecordid:null, // 用户的评价状态
playData:{}, playData:{},
title: 'Hello', title: 'Hello',
isShowEmj: false, isShowEmj: false,
@@ -197,6 +197,7 @@
img:[], img:[],
html:'' html:''
}, },
pingID:null,
productID:null, // 订单商品id productID:null, // 订单商品id
imageStyles:{ imageStyles:{
width:64, width:64,
@@ -267,11 +268,12 @@
this.pjType = 'zhuiping' this.pjType = 'zhuiping'
this.pingjiaShow = true this.pingjiaShow = true
this.productID = val this.productID = val
this.pingID = pingid
}, },
// 追加评论 // 追加评论
zhuiping(){ zhuiping(){
let data = { let data = {
//'oid':'', 'oid': this.userRecordid,
'userId': this.userInfo.id, 'userId': this.userInfo.id,
'bookid': this.productID, 'bookid': this.productID,
'conTent': this.Pform.comment 'conTent': this.Pform.comment
@@ -287,15 +289,21 @@
}).then(res => { }).then(res => {
if (res.code == 0) { if (res.code == 0) {
uni.showToast({ uni.showToast({
title:'成功!', title:'追评成功!',
icon:'success' icon:'success'
}) })
this.pingjiaShow = false this.pingjiaShow = false
this.pjType = '' this.pjType = ''
this.productID = null, this.productID = null,
this.userRecordid = null
this.Pform.comment = '' this.Pform.comment = ''
this.Pform.html = '' this.Pform.html = ''
this.emoji = [] this.emoji = []
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
} }
}) })
}, },
@@ -429,6 +437,11 @@
this.Pform.comment = '' this.Pform.comment = ''
this.Pform.html = '' this.Pform.html = ''
this.emoji = [] this.emoji = []
setTimeout(()=>{
uni.navigateBack({
delta:1
})
},2000)
} }
}) })
}else{ }else{
@@ -505,11 +518,13 @@
}, },
// 获取订单列表 // 获取订单列表
getOrderList() { getOrderList() {
console.log('this.orderType',this.orderType)
this.$http this.$http
.post(`book/buyorder/appGetOrderInfo/${this.orderType}?orderId=${this.orderID}`) .post(`book/buyorder/appGetOrderInfo/${this.orderType}?orderId=${this.orderID}`)
.then(res => { .then(res => {
console.log(res,'res') console.log('res+++',res)
this.orderContet = res.buyOrder this.orderContet = res.buyOrder
this.userRecordid = res.userRecordid
this.productIDs = res.buyOrder.products.map(item => { this.productIDs = res.buyOrder.products.map(item => {
return item.productId return item.productId
}) })

View File

@@ -292,7 +292,8 @@
// this.getYunFei() // this.getYunFei()
}, },
onShow() { onShow() {
console.log('进来了这个页面')
this.getProid() this.getProid()
// return false // return false
// if (this.typeId == 1) { // if (this.typeId == 1) {

View File

@@ -1,5 +1,5 @@
<template> <template>
<view class="container"> <view :class="['container', currentDay == linshiDay ? 'mb50':'']">
<z-nav-bar title="读书打卡"></z-nav-bar> <z-nav-bar title="读书打卡"></z-nav-bar>
<!-- 仿钉钉打卡日历组件 --> <!-- 仿钉钉打卡日历组件 -->
<view class="calendar_container"> <view class="calendar_container">
@@ -15,24 +15,40 @@
<text>今天已签到</text> <text>今天已签到</text>
</view> </view>
</view> </view>
<scroll-view class="scroll-view_H flexbox" scroll-x="true" @scroll="scroll" :scroll-left="scrollLeft"> <!-- <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="" style="padding: 0 6rpx; display: inline-block; width: 20%; box-sizing: border-box; " v-for="(item,index) in 365">
<view <view
:class="['item', signList.indexOf(index+1) != -1 ? 'havSign' : '', :class="['item', signList.indexOf(index+1) != -1 ? 'havSign' : '',
currentDay == index+1 && signList.indexOf(index+1) == -1 ? 'current' : '', currentDay == index+1 && signList.indexOf(index+1) == -1 ? 'current' : '',
linshiDay == index+1 ? 'linshiDay':'']" @click="getInfo(index+1)"> linshiDay == index+1 ? 'linshiDay':'']" @click="getInfo(index+1)">
<span class="day"> <em>{{index+1}}</em> </span> <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> <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="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" class="weidaka">未开始</span>
<span v-if="currentDay == index+1 && signList.indexOf(index+1) == -1" class="daka" @click="kuickSign()">签到</span> <span v-if="currentDay == index+1 && signList.indexOf(index+1) == -1" class="daka" @click="kuickSign()">签到</span>
</view> </view>
</view> </view>
</scroll-view> </scroll-view> -->
<swiper class="swiper scroll-view_H" :current='currentIndex' :indicator-dots="indicatorDots" :autoplay="autoplay" :interval="interval"
:duration="duration">
<swiper-item v-for="(item,index) in dayList" :key="index" class="flexbox swiperPage">
<!-- <view class="swiper-item item" v-for="(item1,index1) in item" :key=""><span class="day"> <em>{{item1}}</em> </span></view> -->
<view v-for="(item1,index1) in item" :key="index1"
:class="['item','swiper-item', signList.indexOf(item1) != -1 ? 'havSign' : '',
currentDay == item1 && signList.indexOf(item1) == -1 ? 'current' : '',
linshiDay == item1 ? 'linshiDay':'']" @click="getInfo(item1)">
<span class="day"> <em>{{item1}}</em> </span>
<u-icon v-if="signList.indexOf(item1) != -1" name="checkbox-mark" color="#fff" size="28" style="margin: 0 auto; width: 28px; text-align: center;"></u-icon>
<span v-if="signList.indexOf(item1) == -1 && currentDay > item1" class="buka">未签</span>
<span v-if="currentDay < item1" class="weidaka">未开始</span>
<span v-if="currentDay == item1 && signList.indexOf(item1) == -1" class="daka" @click="kuickSign()">签到</span>
</view>
</swiper-item>
</swiper>
</view> </view>
<view class="container1"> <view class="container1">
<view class="task" v-if="taskInfo !== {}"> <view class="task" v-if="taskInfo.id" >
<view class="title" v-if="taskInfo.heading"> <view class="title" >
{{taskInfo.heading}} {{taskInfo.heading}}
</view> </view>
<view class="video " v-if="taskInfo.video"> <view class="video " v-if="taskInfo.video">
@@ -46,49 +62,36 @@
<view class="image " v-if="taskInfo.images"> <view class="image " v-if="taskInfo.images">
<!-- 图片形式的任务 --> <!-- 图片形式的任务 -->
<image :src="taskInfo.images" style="width: 100%;" mode="aspectFit"></image> <image :src="taskInfo.images" style="width: 100%;" mode="aspectFit"></image>
</view> </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 class="txt" v-if="taskInfo.content" v-html="taskInfo.content"></view>
</view> </view>
<view class="subContent"> <view v-else>
<u-divider text="今天未发布打卡任务"></u-divider>
</view>
<view :class="['subContent']" v-if="myword.length > 0">
<text class="clockTitle">-- 我的签到 --</text> <text class="clockTitle">-- 我的签到 --</text>
<!-- 未打卡 -->
<!-- 已打卡 --> <!-- 已打卡 -->
<view class="had" v-if="show"> <view class="had" >
<view class="item"> <view class="item" v-for="(item, index) in myword" :key="index">
<h3>#第三课专业变现你的专业 = 超级杠杆 第一笔只是财富#</h3> <h3>#{{item.TaskHeading}}#</h3>
<view class="content"> <view class="content" v-html="item.phtml">
借我一个暮年借我碎片
借我瞻前与顾后借我执拗如少年
借我后天长成的先天借我变如不曾改变
借我素淡的世故和明白的愚借我可预知的险
借我悲怆的磊落借我温软的鲁莽和玩笑的庄严
借我最初与最终的不敢借我不言而喻的不见
借我一场秋啊可你说这已是冬天
</view> </view>
<view class="images flexbox"> <view class="pjimgs flexbox">
<image @click="previewImage()" <view class="item" v-for="(item1,index) in item.clockinimages">
src="https://picx.zhimg.com/70/v2-92392172531ba8e252e3f9afaa4232d2_1440w.awebp?source=172ae18b&biz_tag=Post" <image v-if="item1.length > 10" @click="previewImage(item1)" :src="item1" mode="aspectFill" style="width:100%; height: 50px;"></image>
mode="aspectFill"></image> </view>
<image
src="https://picx.zhimg.com/70/v2-92392172531ba8e252e3f9afaa4232d2_1440w.awebp?source=172ae18b&biz_tag=Post"
mode="aspectFill"></image>
</view> </view>
<view class="opBtns flexbox"> <view class="opBtns flexbox">
<span class="flexbox"><u-icon name="clock" color="#b3b3b3"></u-icon>2023-08-23 14:01</span> <span class="flexbox"><u-icon name="clock" color="#b3b3b3"></u-icon>2023-08-23 14:01</span>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<!-- 他人的打卡记录 --> <!-- 他人的打卡记录 -->
<view class="" v-if="commentsList && commentsList.length > 0"> <view class="allComments" v-if="commentsList && commentsList.length > 0">
<view class="pingjiaBox" v-for="(item, index) in commentsList" :key="index"> <text class="clockTitle">-- 更多签到记录 --</text>
<view :class="['pingjiaBox']" v-for="(item, index) in commentsList" :key="index">
<view class="flexbox"> <view class="flexbox">
<view class="touxiang"> <view class="touxiang">
<image :src="item.avatar" mode="aspectFit"></image> <image :src="item.avatar" mode="aspectFit"></image>
@@ -96,7 +99,7 @@
</view> </view>
<view class="contentBox"> <view class="contentBox">
<div class="pjimgs flexbox"> <div class="pjimgs flexbox">
<view class="item" v-for="(item1,index) in item.images"> <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> <image v-if="item1.length > 10" @click="previewImage(item1)" :src="item1" mode="aspectFill" style="width:100%; height: 50px;"></image>
</view> </view>
@@ -106,7 +109,7 @@
</view> </view>
</view> </view>
<!-- 显示追平 --> <!-- 显示追平 -->
<view class="zhuiping item" v-if="item.zphtml != ''" style="padding-left: 50px;"> <!-- <view class="zhuiping item" v-if="item.zphtml != ''" style="padding-left: 50px;">
<h5 style="color: #dbdbdb; margin:10px;">追评内容</h5> <h5 style="color: #dbdbdb; margin:10px;">追评内容</h5>
<view class="flexbox"> <view class="flexbox">
<view class="contentBox"> <view class="contentBox">
@@ -114,12 +117,12 @@
<text class="time">{{item.followUpdate}}</text> <text class="time">{{item.followUpdate}}</text>
</view> </view>
</view> </view>
</view> </view> -->
</view> </view>
</view> </view>
<view class="quesheng" v-else> <!-- <view class="quesheng" v-else>
<text>暂无评价~</text> <text>暂无评价~</text>
</view> </view> -->
</view> </view>
<u-popup mode="bottom" :show="addTextShow" :round="10" @close="addTextShow=false"> <u-popup mode="bottom" :show="addTextShow" :round="10" @close="addTextShow=false">
<view class="tanchu"> <view class="tanchu">
@@ -154,7 +157,7 @@
</view> </view>
</u-popup> </u-popup>
<view class="leaveBtn" v-if="!addTextShow"> <view class="leaveBtn" v-if="!addTextShow && currentDay == linshiDay">
<button type="primary" plain="true" @click="addTextShow = true">说点什么</button> <button type="primary" plain="true" @click="addTextShow = true">说点什么</button>
</view> </view>
<music-play :playData="playData"></music-play> <music-play :playData="playData"></music-play>
@@ -163,6 +166,7 @@
</template> </template>
<script> <script>
import emojiList1 from '../../bkhumor-emojiplus/emoji/biaoqin.js'
import $http from '@/config/requestConfig.js'; import $http from '@/config/requestConfig.js';
import emotion from '@/bkhumor-emojiplus/components/bkhumor-emojiplus/bkhumor-emojiplus.vue'; import emotion from '@/bkhumor-emojiplus/components/bkhumor-emojiplus/bkhumor-emojiplus.vue';
import zsyCalendar from '@/components/zsy-calendar/zsy-calendar' import zsyCalendar from '@/components/zsy-calendar/zsy-calendar'
@@ -174,17 +178,25 @@
export default { export default {
data() { data() {
return { return {
currentIndex:0,
dayList:[],
indicatorDots: false,
autoplay: false,
interval: 2000,
duration: 500,
commentsList:[], // 他人的打卡列表 commentsList:[], // 他人的打卡列表
addTextShow: false, // 说点什么弹出层 addTextShow: false, // 说点什么弹出层
show: false, show: false,
scrollLeft: 0, // 距离左侧的距离 scrollLeft: 0, // 距离左侧的距离
currentDay:1, // 当前打卡位置 currentDay:0, // 当前打卡位置
currentTid:null, // 今天的任务id currentTid:null, // 今天的任务id
emojiIcon: 'cuIcon-emoji', emojiIcon: 'cuIcon-emoji',
windowWidth: 0, windowWidth: 0,
taskInfo:{ taskInfo:{
id:null,
heading:'' heading:''
}, },
list3:[], // 时间日期
emoji: [], emoji: [],
signList:[], // 已打卡天 signList:[], // 已打卡天
linshiDay:null, linshiDay:null,
@@ -196,10 +208,12 @@
videoContext: null, videoContext: null,
innerAudioContext: null, // 音频对象 innerAudioContext: null, // 音频对象
poster: '', poster: '',
myword:[], // 我的打卡内容
formData: { formData: {
// 打卡表单 // 打卡表单
content: '', content: '',
images: [] images: [],
imagesStr: []
}, },
currentAudio: { currentAudio: {
poster: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png', poster: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png',
@@ -223,8 +237,10 @@
}, },
onLoad(e) { onLoad(e) {
this.bookid = e.bookid this.bookid = e.bookid
this.windowWidth = uni.getSystemInfoSync().windowWidth; this.windowWidth = uni.getSystemInfoSync().windowWidth;
this.getmySign() this.initDay()
this.getmySign()
}, },
onReady() { onReady() {
this.videoContext = uni.createVideoContext('myVideo') this.videoContext = uni.createVideoContext('myVideo')
@@ -235,6 +251,26 @@
...mapState(['userInfo']) ...mapState(['userInfo'])
}, },
methods: { methods: {
group(array, subGroupLength) {
let index = 0;
let newArray = [];
while(index < array.length) {
newArray.push(array.slice(index, index += subGroupLength));
}
return newArray;
},
// 初始化day
initDay(){
var listint = 1
var arr = []
var arr1 = []
for (var i= 1; i<=365; i++) {
arr.push(i)
}
arr1 = this.group(arr, 5)
this.dayList = arr1
// console.log(arr1,'+++++++++++++')
},
// 放大图片 // 放大图片
previewImage(url){ previewImage(url){
console.log(url) console.log(url)
@@ -252,10 +288,12 @@
.post('book/clockinPunch/clockindays', data) .post('book/clockinPunch/clockindays', data)
.then(res => { .then(res => {
if (res.code == 0) { if (res.code == 0) {
this.currentDay = res.daysBetween this.currentDay = res.daysBetween
this.linshiDay = res.daysBetween
this.signList = res.dayslist this.signList = res.dayslist
console.log(res, '打卡参数') console.log(res, '打卡参数')
let zheng = Math.floor(this.currentDay / 5) let zheng = Math.floor(this.currentDay / 5)
this.currentIndex = zheng
let yu = this.currentDay % 5 let yu = this.currentDay % 5
if(this.currentDay <=5){this.scrollLeft = 0} if(this.currentDay <=5){this.scrollLeft = 0}
@@ -265,14 +303,44 @@
} }
if(zheng > 1 && yu == 0){ if(zheng > 1 && yu == 0){
this.scrollLeft = (this.windowWidth - 30) * (zheng - 1) this.scrollLeft = (this.windowWidth - 30) * (zheng - 1)
this.currentIndex -= 1
} }
// console.log(zheng, yu, this.scrollLeft, this.windowWidth, 'this.scrollLeft') // console.log(zheng, yu, this.scrollLeft, this.windowWidth, 'this.scrollLeft')
this.getTask(this.currentDay) this.getTask(this.currentDay)
this.getAllSign(this.currentDay)
} }
}); });
}, },
// 获取当天我的发布内容
getmyWord(){
this.$http
.post('book/clockin/myinfolist?userid='+this.userInfo.id+'&taskid='+ this.taskInfo.id + '&bookid='+this.bookid)
.then(res => {
console.log(res,'当天我的打卡内容')
if(res.code == 0 && res.productlist.length > 0 ){
var arr = []
res.productlist.forEach((item1)=>{
var pjstr = ''
var imgs = []
imgs = item1.clockinimages.split(',')
pjstr = this.getHtmlComment(item1.content)
item1.clockinimages = imgs
item1.phtml = pjstr
arr.push(item1)
})
this.myword = arr
// console.log(this.myword,'this.myword')
}else{
this.myword = []
}
})
.catch(e => {
console.log(e)
})
},
// 获取签到详情 // 获取签到详情
getInfo(index){ getInfo(index){
if(this.currentDay < index){ if(this.currentDay < index){
@@ -281,32 +349,52 @@
icon: 'none' icon: 'none'
}) })
}else{ }else{
this.linshiDay = index this.linshiDay = index
this.getTask(index) this.getTask(index)
this.getAllSign(index)
} }
}, },
// 获取某天的签到列表信息 // 获取某天的签到列表信息
getAllSign(index){ getAllSign(val){
console.log(val,'-----------')
let data = { let data = {
'bookid': this.bookid, 'bookid': this.bookid,
'limit': 5, 'limit': 5,
'page': this.page, 'page': this.page,
'taskid': index 'taskid': val.id
} }
console.log(data)
this.$http this.$http
.post('book/clockin/applist', data) .post('book/clockin/applist', data)
.then(res => { .then(res => {
if (res.code == 0) { if (res.code == 0) {
console.log(res, '所有人打卡信息') console.log(res, '所有人打卡信息')
this.commentsList = res.page.list if(res.list.length > 0){
var arr = res.list
for (var i=0; i<arr.length; i++) {
var arr1 = []
var pjstr = ''
// console.log(arr[i].content,'arr[i].content')
pjstr = this.getHtmlComment(arr[i].content)
// console.log(pjstr,'pjstr')
arr1 = arr[i].images.split(',')
arr[i].images = arr1
arr[i].phtml = pjstr
// console.log(arr1,'arr1')
}
// console.log(arr,'res.page.list')
this.commentsList = arr
}else{
this.commentsList = []
}
} }
}); });
}, },
// 获取对应签到内容 // 获取对应签到内容
getTask(index){ getTask(index){
uni.showLoading()
let data = { let data = {
'bookid': this.bookid, 'bookid': this.bookid,
'days': index 'days': index
@@ -317,22 +405,32 @@
.then(res => { .then(res => {
if (res.code == 0) { if (res.code == 0) {
console.log(res, '任务信息') console.log(res, '任务信息')
if(res.page.list.length > 0){
this.taskInfo = res.page.list[0] this.taskInfo = res.page.list[0]
this.taskInfo.video != ''? this.poster = this.taskInfo.video + "?x-oss-process=video/snapshot,t_0,f_jpg" : '' this.taskInfo.video != ''? this.poster = this.taskInfo.video + "?x-oss-process=video/snapshot,t_0,f_jpg" : ''
this.getmyWord()
this.getAllSign(this.taskInfo)
}else{
this.taskInfo = {}
this.poster = ''
}
} }
uni.hideLoading()
}); }).catch(e => {
uni.hideLoading()
})
}, },
// 快捷签到 // 快捷签到
kuickSign(){ kuickSign(){
console.log()
let data = { let data = {
"bookId": this.bookid, "bookId": this.bookid,
"userId": this.userInfo.id, "userId": this.userInfo.id,
"tid": this.taskInfo.id, "tid": this.taskInfo.id,
"days":this.currentDay "days":this.currentDay
} }
// console.log(data,'data')
$http.request({ $http.request({
url : 'book/clockinPunch/save', url : 'book/clockinPunch/save',
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档 method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
@@ -344,13 +442,13 @@
if (res.code == 0) { if (res.code == 0) {
//console.log(res, '快捷签到') //console.log(res, '快捷签到')
uni.showToast({ uni.showToast({
title:res.msg title:'签到成功'
}) })
this.addTextShow = false this.addTextShow = false
this.formData.content = '' this.formData.content = ''
this.formData.images = [] this.formData.images = []
this.getmySign() this.getmySign()
this.getAllSign(this.currentDay) this.getAllSign(this.taskInfo)
} }
}); });
@@ -360,20 +458,16 @@
let data = { let data = {
'bookId': this.bookid, 'bookId': this.bookid,
"userId": this.userInfo.id, "userId": this.userInfo.id,
"taskId": this.currentDay, "taskId": this.taskInfo.id,
"dayId": this.currentDay,
"content": this.formData.content, "content": this.formData.content,
"images": this.formData.images.join(), // "images": this.formData.imagesStr.join(),
"imageeStrings": this.formData.images,
} }
// console.log(data,'data')
var surl = '' console.log(data,'data')
if(this.signList.indexOf(this.currentDay) != -1){
surl='book/clockin/update'
}else{
surl = 'book/clockin/save'
}
$http.request({ $http.request({
url : surl, url : 'book/clockin/save',
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档 method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data, data,
header: { //默认 无 说明:请求头 header: { //默认 无 说明:请求头
@@ -383,13 +477,15 @@
if (res.code == 0) { if (res.code == 0) {
//console.log(res, '快捷签到') //console.log(res, '快捷签到')
uni.showToast({ uni.showToast({
title:res.msg title:'发布成功'
}) })
this.addTextShow = false this.addTextShow = false
this.formData.content = '' this.formData.content = ''
this.formData.images = [] this.formData.images = []
this.formData.imagesStr = []
this.getmySign() this.getmySign()
this.getAllSign(this.currentDay) this.getTask()
} }
}); });
@@ -450,7 +546,7 @@
// 处理格式 // 处理格式
getHtmlComment(comment) { getHtmlComment(comment) {
// 格式化html // 格式化html
// 这里处理 链接 换行符 // 这里处理 链接 换行符
let replacedStr = comment.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => { let replacedStr = comment.replace(/\[([^(\]|\[)]*)\]/g, (item, index) => {
// console.log(item, index) // console.log(item, index)
var indexss = emojiList1.findIndex(item1 => item1.alt === item) var indexss = emojiList1.findIndex(item1 => item1.alt === item)
@@ -491,7 +587,8 @@
success: (res) => { success: (res) => {
that.formData.images.push({ that.formData.images.push({
url: JSON.parse(res.data).url url: JSON.parse(res.data).url
}) })
console.log(that.formData.images,'that.formData.images')
} }
}); });
} }
@@ -518,6 +615,21 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.pjimgs{ margin: 10px 0;flex-wrap: wrap; display: flex;
.item{width: 23%; margin-right: 10px;
image{ }
}
}
.contentBox{width: calc(100% - 50px);box-sizing: border-box; padding-left: 20rpx;
.content{font-size: 28rpx; line-height: 40rpx;}
.time{font-size: 24rpx; color: #999; margin-top: 6rpx; float: right;}
}
.touxiang{width:50px; overflow: hidden; text-align: center;
image{width:50px !important; padding: 3px; height: 50px !important; border: 1px solid #eee; border-radius: 64px; overflow: hidden;;}
.username{font-size: 24rpx; color: #999; margin-top: 6rpx; }
}
.allComments{ background-color: #fff; margin-top: 20rpx; padding: 20rpx; margin-bottom: 40rpx; }
.quesheng{text-align: center; margin-top: 100rpx; color: #8b8a91;} .quesheng{text-align: center; margin-top: 100rpx; color: #8b8a91;}
.haveSignText{color: #999 ;} .haveSignText{color: #999 ;}
.calendar_info { .calendar_info {
@@ -537,11 +649,13 @@
.scroll-view_H { .scroll-view_H {
white-space: nowrap; white-space: nowrap;
margin: 20px 0; margin: 20px 0; height: 120rpx !important;
width: 100%; width: 100%;
.swiperPage{ justify-content: space-between; height: 120rpx !important;}
.item { .item { box-sizing: border-box;
width: calc(20% - 12rpx) !important;
border: 1px dashed #999; border: 1px dashed #999;
height: 120rpx;
width: calc(100% - 6rpx); width: calc(100% - 6rpx);
// margin: 0 6rpx; // margin: 0 6rpx;
text-align: center; text-align: center;
@@ -555,7 +669,7 @@
color: #999; color: #999;
em { em {
font-size: 36rpx; font-size: 30rpx;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
padding-right: 2px; padding-right: 2px;
@@ -567,6 +681,7 @@
} }
.buka { .buka {
font-size: 24rpx;
display: inline-block; padding: 0 6rpx; display: inline-block; padding: 0 6rpx;
color: #888; color: #888;
// border: 1px solid #888; // border: 1px solid #888;
@@ -577,12 +692,13 @@
.weidaka { .weidaka {
color: #A3B4B5; color: #A3B4B5;
margin: 10px 0; font-size: 24; margin: 10px 0; font-size: 24rpx;
border-radius: 20rpx; border-radius: 20rpx;
margin-bottom: 0; margin-bottom: 0;
display: block; display: block;
} }
.daka{ .daka{
font-size: 24rpx;
display: inline-block; padding: 0 6rpx; display: inline-block; padding: 0 6rpx;
border: 1px solid #55aaff; border: 1px solid #55aaff;
color: #55aaff; color: #55aaff;
@@ -600,13 +716,13 @@
display: inline-block; display: inline-block;
background-color: #55aa7f; background-color: #55aa7f;
border-radius: 20rpx; border-radius: 20rpx;
padding: 6px 6px; padding: 6px 3px;
.day { .day {
font-size: 26rpx; font-size: 26rpx;
color: #fff; color: #fff;
em { em {
font-size: 32rpx; font-size: 30rpx;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
padding-right: 2px; padding-right: 2px;
@@ -625,11 +741,12 @@
background-color: #edf9ff; background-color: #edf9ff;
border-radius: 20rpx; border-radius: 20rpx;
padding: 6px 6px; padding: 6px 6px;
.day { .day {
font-size: 26rpx; font-size: 26rpx;
color: #55aaff; color: #55aaff;
em { em {
font-size: 32rpx; font-size: 30rpx;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
padding-right: 2px; padding-right: 2px;
@@ -637,6 +754,9 @@
} }
} }
.item.linshiDay{ .item.linshiDay{
.daka{
color: #fff; border-color:#fff;
}
border: 1px solid #55aaff; border: 1px solid #55aaff;
text-align: center; text-align: center;
@@ -714,15 +834,15 @@
background-color: #fff; background-color: #fff;
overflow: hidden; overflow: hidden;
.clockTitle {
}
.clockTitle {
color: #55aa7f; color: #55aa7f;
font-size: 38rpx; font-size: 38rpx;
text-align: center; text-align: center;
display: block; display: block;
margin-top: 30rpx; margin-top: 30rpx; margin-bottom: 30rpx;
} }
}
.container1 { .container1 {
.margin-top { .margin-top {
margin-top: 30rpx; margin-top: 30rpx;
@@ -841,4 +961,5 @@
.flexbox { .flexbox {
display: flex; display: flex;
} }
.mb50{margin-bottom: 50rpx;}
</style> </style>

View File

@@ -0,0 +1,393 @@
<template>
<view class="container">
<z-nav-bar title="打卡记录"></z-nav-bar>
<view class="calendar_container">
<zsy-calendar :mode="mode" @change="change" />
</view>
<view class="container1">
<view class="subContent">
<!-- 已打卡 -->
<view class="had">
<view class="item flexbox">
<view class="dateName flexbox">
<span><em>365</em></span>
</view>
<view class="bookinfo">
<view class="case">
<view class="book flexbox">
<image src="../../static/icon/x1.jpg" mode="aspectFill"></image>
<view class="clockInfo">
<span>中医免疫学</span>
<h3>#第三课专业变现你的专业 = 超级杠杆 第一笔只是财富#</h3>
</view>
</view>
<view class="content">
借我一个暮年借我碎片
借我瞻前与顾后借我执拗如少年
借我后天长成的先天借我变如不曾改变
借我素淡的世故和明白的愚借我可预知的险
借我悲怆的磊落借我温软的鲁莽和玩笑的庄严
借我最初与最终的不敢借我不言而喻的不见
借我一场秋啊可你说这已是冬天
<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>
<span class="viewMore"><u-icon style="display: inline-block;" name="arrow-down"
color="#409eff"></u-icon>查看全部</span>
</view>
</view>
<view class="case">
<view class="book flexbox">
<image src="../../static/icon/x1.jpg" mode="aspectFill"></image>
<view class="clockInfo">
<span>中医免疫学</span>
<h3>#第三课专业变现你的专业 = 超级杠杆 第一笔只是财富#</h3>
</view>
</view>
<view class="content">
借我一个暮年借我碎片
借我瞻前与顾后借我执拗如少年
借我后天长成的先天借我变如不曾改变
借我素淡的世故和明白的愚借我可预知的险
借我悲怆的磊落借我温软的鲁莽和玩笑的庄严
借我最初与最终的不敢借我不言而喻的不见
借我一场秋啊可你说这已是冬天
<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>
<span class="viewMore"><u-icon style="display: inline-block;" name="arrow-down"
color="#409eff"></u-icon>查看全部</span>
</view>
</view>
</view>
</view>
<view class="item flexbox">
<view class="dateName flexbox">
<span><em>36</em></span>
</view>
<view class="bookinfo">
<view class="case">
<view class="book flexbox">
<image src="../../static/icon/x1.jpg" mode="aspectFill"></image>
<view class="clockInfo">
<span>中医免疫学</span>
<h3>#第三课专业变现你的专业 = 超级杠杆 第一笔只是财富#</h3>
</view>
</view>
<view class="content">
借我一个暮年借我碎片
借我瞻前与顾后借我执拗如少年
借我后天长成的先天借我变如不曾改变
借我素淡的世故和明白的愚借我可预知的险
借我悲怆的磊落借我温软的鲁莽和玩笑的庄严
借我最初与最终的不敢借我不言而喻的不见
借我一场秋啊可你说这已是冬天
<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>
<span class="viewMore"><u-icon style="display: inline-block;" name="arrow-down"
color="#409eff"></u-icon>查看全部</span>
</view>
</view>
<view class="case">
<view class="book flexbox">
<image src="../../static/icon/x1.jpg" mode="aspectFill"></image>
<view class="clockInfo">
<span>中医免疫学</span>
<h3>#第三课专业变现你的专业 = 超级杠杆 第一笔只是财富#</h3>
</view>
</view>
<view class="content">
借我一个暮年借我碎片
借我瞻前与顾后借我执拗如少年
借我后天长成的先天借我变如不曾改变
借我素淡的世故和明白的愚借我可预知的险
借我悲怆的磊落借我温软的鲁莽和玩笑的庄严
借我最初与最终的不敢借我不言而喻的不见
借我一场秋啊可你说这已是冬天
<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>
<span class="viewMore"><u-icon style="display: inline-block;" name="arrow-down"
color="#409eff"></u-icon>查看全部</span>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<music-play :playData="playData"></music-play>
<z-navigation></z-navigation>
</view>
</template>
<script>
import zsyCalendar from '@/components/zsy-calendar/zsy-calendar'
import musicPlay from '@/components/music.vue'
import {
mapState
} from 'vuex';
export default {
data() {
return {
playData: {},
mode: 'open',
status : 0
}
},
// 返回顶部
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
// 下拉刷新
onReachBottom() {
this.status = 0
if (this.bookScreen.page < this.totalPage) {
this.bookScreen.page = this.bookScreen.page + 1
setTimeout(() => {
this.$http
// .post('book/book/list', this.bookScreen)
.post('book/shopproduct/selectList?limit=8&page=1&key='+this.bookScreen.bookName)
.then(res => {
this.totalPage = res.page.totalPage
for (let i in res.page.list) {
this.bookList.push(res.page.list[i])
}
});
}, 1000)
} else {
this.status = 1
}
},
onLoad() {
this.getmyWord()
},
methods: {
change(e) {
console.log(e)
},
getmyWord(){
this.$http
.post('book/clockin/myinfo?userid='+this.userInfo.id)
.then(res => {
console.log(res,'我的打卡内容')
})
.catch(e => {
console.log(e)
})
},
},
components: {
musicPlay,
zsyCalendar
},
computed:{
...mapState(['userInfo'])
}
}
</script>
<style lang="scss" scoped>
.listenList{
.wrap{width: 150rpx;}
}
.task {
margin-top: 40rpx 20rpx;
.taskinfo {
video {
width: 100%;
}
}
}
.subContent {
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: #f5f5f5;
//padding: 30rpx;
box-sizing: border-box;
}
.had {
margin-top: 30rpx;
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;
}
}
.item {
padding-left: 20rpx;
margin-bottom: 40rpx;
background-color: #fff;
justify-content: space-between;
.dateName {
color: #444;
text-align: center;
align-items: center;
width: 80rpx;
padding-right: 20rpx;
border-right: 1px solid #eee;
span {
display: inline-block;
height: 120rpx;
padding: 20rpx 0;
border-radius: 50rpx;
width: 100%;
background-color: #d9e8f7;
text-align: center;
em {
font-weight: bold;
font-style: normal;
}
}
}
.bookinfo {
text-align: center;
// width: 100%;
// padding: 20rpx;
margin-left: 20rpx;
.case{ margin-top:60rpx; background-color: #fff; padding: 20rpx;}
.content {
position: relative; padding-bottom: 60rpx; height: 60px; overflow: hidden;
}
.book {
image {
width:200rpx;
height: 150rpx;
margin: 0 auto;
}
.clockInfo{text-align: left; margin-left: 20rpx;}
span {
color: #444;
display: block;
font-weight: bold;
margin-bottom: 20rpx;
}
}
}
}
}
.viewMore {
position: absolute;
bottom: 5rpx;
right: 0; color: #409eff;
z-index: 1; text-align: right;
width: 200rpx; background-image: url('@/static/icon/zuotouming.png'); background-position: right; background-size: cover; background-repeat: no-repeat;
}
.flexbox {
display: flex;
}
</style>

413
pages/clock/clockList.vue Normal file
View File

@@ -0,0 +1,413 @@
<template>
<view class="container">
<z-nav-bar title="我的打卡签到记录"></z-nav-bar>
<!-- <view class="calendar_container">
<zsy-calendar :mode="mode" @change="change" />
</view> -->
<view class="books">
<view class="" style="background-color: #fff; padding: 10rpx;">
<text style="font-size: 24rpx; color: #888;" v-if="bookList.length > 0">我的打卡书籍</text>
<text style="font-size: 24rpx; color: #888;" v-else>暂无可打卡书籍</text>
</view>
<scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" :scroll-left="scrollLeft">
<view class="listenList flexbox" v-if="bookList.length > 0">
<view :class="['item', selectIndex == index ? 'active' : '']" v-for="(item,index) in bookList" :key="index">
<view class="videoBox" @click="selectOne(item.book,index)">
<image v-if="item.book.images != ''" :src="item.book.images" mode="scaleToFill"></image>
<image v-else src="../../static/icon/wufeng.jpg" mode="scaleToFill"></image>
</view>
<text class="bookName">{{item.book.name}}</text>
</view>
</view>
</scroll-view>
</view>
<view class="container1">
<view class="subContent" v-if="status==0">
<!-- 已打卡 -->
<view class="had" v-if="recordList.length> 0">
<view class="item">
<view class="bookinfo">
<view class="case" v-for="(item, index) in recordList" :key="index">
<view class="book flexbox" >
<!-- <image src="../../static/icon/x1.jpg" mode="aspectFill"></image> -->
<view class="clockInfo" >
<!-- <span>中医免疫学</span> -->
<h3><span class="day"> <em>{{item.dayId}}</em> </span><br/>#{{item.TaskHeading}}#</h3>
</view>
</view>
<view :class="['content',item.zhankai ? 'active' : '']" >
<view class="texttt" v-html="item.phtml" ></view>
<view class="images flexbox" v-if="item.clockinimages.length>0">
<view class="box" v-for="(item1,index1) in item.clockinimages">
<image @click="previewImage(item1)"
:src="item1"
mode="aspectFill"></image>
</view>
</view>
<view class="opBtns flexbox">
<span class="flexbox"><u-icon name="clock" color="#b3b3b3"></u-icon>{{item.createTime}}</span>
</view>
<span class="viewMore" v-if="!item.zhankai" @click="changeHeight(item, index)">
<u-icon style="display: inline-block;" name="arrow-down"
color="#55aa00"></u-icon>
展开</span>
<span class="viewMore" v-else @click="changeHeight(item, index)">
<u-icon style="display: inline-block;" name="arrow-down"
color="#55aa00"></u-icon>
收起</span>
</view>
</view>
</view>
</view>
</view>
<view v-else>
<u-divider text="暂无打卡记录哦~"></u-divider>
</view>
</view>
<view v-if="status==1">
<u-divider text="全部加载完成"></u-divider>
</view>
<view style="padding-bottom: 20rpx;">
<u-back-top :scroll-top="scrollTop"></u-back-top>
</view>
</view>
<music-play :playData="playData"></music-play>
<z-navigation></z-navigation>
</view>
</template>
<script>
import emojiList1 from '../../bkhumor-emojiplus/emoji/biaoqin.js'
import zsyCalendar from '@/components/zsy-calendar/zsy-calendar'
import musicPlay from '@/components/music.vue'
import {
mapState
} from 'vuex';
export default {
data() {
return {
playData: {},
mode: 'open',
status: 0,
scrollLeft: 0,
recordList: [],
bookList: [],
scrollTop: 0,
bookinfo:{},
selectIndex:0
}
},
// 返回顶部
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
// 下拉刷新
onReachBottom() {
this.status = 0
},
onLoad() {
this.getfreeBook()
},
methods: {
selectOne(val,index){
// 点击某一个图书
uni.showLoading()
this.bookinfo = val
this.selectIndex = index
this.getmyWord()
},
scroll(e) {
},
// 获取打卡图书列表
getfreeBook() {
this.$http
.post('book/userebookbuy/appbooklist', {
'userId': this.userInfo.id,
'page': this.page,
'limit': 100
})
.then(res => {
if (res.code == 0) {
// this.ygtotalPage = res.resultlist.totalCount
if(res.resultlist.length > 0) {
this.bookList = res.resultlist
this.bookinfo = this.bookList[0].book
console.log(res, '已购买')
this.getmyWord()
// this.status = 3
}else{
this.bookList = []
}
}
});
},
change(e) {
console.log(e)
},
// 放大图片
previewImage(url){
console.log(url, 'url')
uni.previewImage({
urls: [url]
});
},
// 处理展开或者合并
changeHeight(val, index){
this.recordList[index].zhankai = !this.recordList[index].zhankai
},
// 处理格式
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>');
},
getmyWord() {
console.log(this.userInfo.id,this.bookinfo.id,'++++++++')
this.$http
.post('book/clockin/myinfo?userid=' + this.userInfo.id + '&bookid='+ this.bookinfo.id)
.then(res => {
console.log(res, '我的打卡内容')
if (res.code == 0 && res.ClockinList.length > 0) {
// this.recordList = res.ClockinList
var arr = []
res.ClockinList.forEach((item1)=>{
var pjstr = ''
var imgs = []
imgs = item1.clockinimages.split(',')
pjstr = this.getHtmlComment(item1.content)
item1.clockinimages = imgs
//console.log(pjstr,'99999999999----------')
item1.zhankai = false
item1.phtml = pjstr
arr.push(item1)
})
this.recordList = arr
} else {
this.recordList = []
}
uni.hideLoading()
})
.catch(e => {
console.log(e.msg)
uni.hideLoading()
})
},
},
components: {
musicPlay,
zsyCalendar
},
computed: {
...mapState(['userInfo'])
}
}
</script>
<style lang="scss" scoped>
.scroll-view_H{background-color: #fff; padding:10rpx }
.listenList { background-color: #fff; padding: 5rpx 0;
.item { padding: 10rpx; overflow: hidden;
width: 150rpx !important; margin-right: 20rpx; border: 1px solid #fff; border-radius: 10rpx;
.videoBox{
image{display: block; width:130rpx;
height: 170rpx;
}
}
.bookName{display: block; margin-top: 20rpx; color: #666; font-size: 24rpx; white-space: nowrap;
overflow-x: hidden; overflow: hidden;
text-overflow: ellipsis;}
}
.item.active{margin-right: 20rpx; border: 1px solid #55aa00; border-radius: 10rpx;}
}
.task {
margin-top: 40rpx 20rpx;
.taskinfo {
video {
width: 100%;
}
}
}
.subContent {
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: #f5f5f5;
//padding: 30rpx;
box-sizing: border-box;
}
.had {
margin-top: 30rpx;
h3 {
color: #8c9a92;
font-size: 34rpx;
}
.content {
width: 100% !important; overflow: hidden;
line-height: 60rpx;
margin-top: 10rpx;
font-size: 30rpx;
color: #0e0e15;
.texttt{margin-top: 10rpx; text-align: left !important; word-wrap:break-word !important; word-break:break-all; width: 100%;
font-size: 30rpx;
color: #888;}
}
.images {
height: 150rpx;
overflow: hidden;
margin-top: 30rpx;
.box{
width: 150rpx;height: 150rpx; margin: 0 10rpx;
}
image {
width: 150rpx;
}
}
.opBtns {
margin-top: 30rpx;
span {
color: #b3b3b3;
padding-left: 20rpx;
font-size: 24rpx;
}
}
.item {
padding-left: 20rpx;
margin-bottom: 40rpx;
background-color: #fff;
justify-content: space-between;
.dateName {
color: #444;
text-align: center;
align-items: center;
width: 80rpx;
padding-right: 20rpx;
border-right: 1px solid #eee;
span {
display: inline-block;
height: 120rpx;
padding: 20rpx 0;
border-radius: 50rpx;
width: 100%;
background-color: #d9e8f7;
text-align: center;
em {
font-weight: bold;
font-style: normal;
}
}
}
.bookinfo {
text-align: center;
// width: 100%;
// padding: 20rpx;
margin-left: 20rpx;
.case {
margin-top: 30rpx;
background-color: #fff; padding-bottom: 30rpx !important;
padding:10rpx;
border-bottom: 1px solid #efefef; margin-bottom: 20rpx ;
}
.content {
position: relative;
padding-bottom: 60rpx;
height: 60px;
overflow: hidden;
}
.content.active{height: auto !important;}
.book {
image {
width: 200rpx;
height: 150rpx;
margin: 0 auto;
}
.clockInfo { margin-bottom: 10rpx;
text-align: left;
.day{ color: #55aa7f; margin-bottom: 20rpx ; font-size: 36rpx !important; display: inline; padding: 20rpx; border-radius: 10rpx;}
em{font-style: normal; font-size: 60rpx !important; padding: 0 10rpx;}
}
span {
color: #444;
display: block;
font-weight: bold;
margin-bottom: 20rpx;
}
}
}
}
}
.viewMore {
position: absolute;
bottom: 5rpx;
right: 0;
color: #55aa00;
z-index: 1;
text-align: right;
width: 200rpx;
background-image: url('@/static/icon/zuotouming.png');
background-position: right;
background-size: cover;
background-repeat: no-repeat;
}
.flexbox {
display: flex;
}
</style>

213
pages/clock/index.vue Normal file
View File

@@ -0,0 +1,213 @@
<template>
<view>
<z-nav-bar title="读书打卡"></z-nav-bar>
<view class="listenList" v-if="bookList.length > 0">
<view class="wrap" >
<u-row gutter="16" justify="flex-start">
<u-col span="4" v-for="(item,index) in bookList" :key="index">
<view class="videoBox demo-layout bg-purple" @click="goToClock(item.book)">
<image v-if="item.book.images != ''" :src="item.book.images" mode="scaleToFill" ></image>
<image v-else src="../../static/icon/wufeng.jpg" mode="scaleToFill" ></image>
</view>
<text class="bookName">{{item.book.name}}</text>
</u-col>
</u-row>
</view>
</view>
<music-play :playData="playData"></music-play>
<z-navigation></z-navigation>
</view>
</template>
<script>
import {
mapState
} from 'vuex';
import musicPlay from '@/components/music.vue'
export default {
data() {
return {
playData:{},
bookList:[],
page:1, // 页码
}
},
onLoad() {
this.getfreeBook()
},
methods: {
// 跳转到打卡页面
goToClock(val){
if(val.clockIn != 1){
uni.showModal({
title: '提示',
cancelText: '暂不购买',
confirmText:'立即购买',
content: '购买后才可参与本书打卡哦~',
success: function (res) {
if (res.confirm) {
console.log('点击了去购买');
}
}
});
}else{
console.log(val,'val')
this.onPageJump('../clock/clock?bookid='+val.id)
}
},
// 获取打卡图书
getfreeBook(){
this.$http
.post('book/userebookbuy/appbooklist', {
// .post('book/userebookbuy/buylist', {
// .post('book/buyorderdetail/querybuy', {
'userId': this.userInfo.id,
// 'page':this.page,
// 'limit':100
})
.then(res => {
if(res.code == 0){
//this.ygtotalPage = res.resultlist.totalCount
this.bookList = res.resultlist
console.log(res,'已购买')
this.status = 3
}
});
},
// 跳转
onPageJump(url) {
uni.navigateTo({
url: url
});
},
},
computed: {
...mapState(['userInfo'])
},
components: {
musicPlay,
}
}
</script>
<style lang="scss" scoped>
@import '@/style/mixin.scss';
.contentButton{margin: 20rpx 0;}
.btns{margin-top: 15rpx; background-color: #f1f1f1; border-radius: 10rpx; font-size: 28rpx; justify-content: space-between;
}
.quesheng{text-align: center; margin-top: 100rpx; color: #8b8a91;}
.bookName{
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
font-size: 30rpx; color: #333; padding: 10rpx 0;
}
.videoBox{position: relative;}
.playButton{position: absolute; z-index: 1; right: 4px; bottom: 4px; padding: 5px; border-radius: 100%; }
uni-image {
width:auto !important;
height: 350rpx;
}
.u-row{flex-wrap: wrap;}
.u-col{overflow: hidden; height: 250px; margin-bottom: 30rpx; }
.listenList{padding: 10rpx; box-sizing: border-box; width: calc(100% - 10rpx);}
.flexbox{display: flex;}
.scroll-Y {
height: 300rpx;
}
.scroll-view_H {
white-space: nowrap;
width: 100%;
}
.scroll-view-item {
height: 300rpx;
line-height: 300rpx;
text-align: center;
font-size: 36rpx;
}
.scroll-view-item_H {
display: inline-block;
width: 60%;
height: 300rpx;
line-height: 300rpx;
text-align: center;
font-size: 36rpx;
}
.head_line {
margin: 50rpx 0;
b {
display: inline-block;
width: 12rpx;
height: 40rpx;
background-color: #54a966;
vertical-align: bottom;
margin: 0 20rpx 0 0;
}
text {
font-size: 32rpx;
font-weight: bold;
}
i {
float: right;
font-style: normal;
color: #8b8a91;
font-size: 24rpx;
margin: 5rpx 35rpx 0 0;
}
}
.home_bg {
background-image: url('@/static/icon/home_bg.jpg');
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
padding: 100rpx 0 40rpx 0;
position: relative;
.icon_hua_1 {
margin: 0 auto;
width: 150rpx;
height: 150rpx;
}
.search_box {
width: 90%;
height: 64upx;
background-color: #fff;
border-radius: 32upx;
display: flex;
align-items: center;
padding: 0upx 40upx;
position: absolute;
margin-left: -46%;
left: 50%;
bottom: -30rpx;
box-shadow: 0 0px 10px 1px #54a96633;
.prompt {
color: #cccccc;
}
.icon_search {
background-image: url('@/static/icon/map_ic_search.png');
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
width: 29upx;
height: 28upx;
margin-right: 20upx;
}
}
}
</style>

View File

@@ -2,21 +2,45 @@
<view> <view>
<!-- 公共组件-每个页面必须引入 --> <!-- 公共组件-每个页面必须引入 -->
<!-- <public-module></public-module> --> <!-- <public-module></public-module> -->
<z-nav-bar title="我的图书"></z-nav-bar> <!-- <z-nav-bar title="我的图书"></z-nav-bar> -->
<view class="home_bg" > <view class="home_bg " >
<image src="../../static/icon/home_icon_1.png" mode="aspectFit" class="icon_hua_1"></image> <view class="flexbox" style=" justify-content: space-between; ">
<view class="search_box" @click="onPageJump('./searchFor')"> <view class="icon_hua">
<text class="icon_search"></text> <image src="../../static/icon/home_icon_3.png" mode="aspectFit" class="icon_hua_1"></image>
<text class="prompt">搜索...</text> </view>
<view class="search_box flexbox" @click="onPageJump('../peanut/searchFor')">
<view class="search">
<text class="icon_search"></text>
<text class="prompt">请输入想要搜索的书名</text>
</view>
</view>
<view class="searBtn flexbox">
<text>搜索</text>
</view>
</view>
<view class="home_lunbo">
<u-swiper :list="list3" indicator indicatorMode="line" circular style="height: 180rpx;"></u-swiper>
</view>
</view>
<!-- <view class="contentButton">
<u-tabs :scrollable="false" bg-color="#d4d4d4" active-color="#2979ff" inactive-color="#606266" bar-height="10" :list="contentButtonList" @click="contentButtonClick" lineWidth="42" :inactiveStyle="{fontSize:'32rpx'}" :activeStyle="{color: '#303133',fontWeight: 'bold', transform: 'scale(1.01)'}"></u-tabs>
</view> -->
<view class="" style="padding: 20rpx;">
<view class="mytabs flexbox">
<view :class="['item','item1', contentShow == 1 ? 'active' :'']" @click="setData(1)">
已购图书
</view>
<view :class="['item','item2', contentShow == 2 ? 'active' :'']" @click="setData(2)">
推荐图书
</view> </view>
</view> </view>
<view class="contentButton">
<u-tabs :scrollable="false" bg-color="#d4d4d4" active-color="#2979ff" inactive-color="#606266" bar-height="10" :list="contentButtonList" @click="contentButtonClick" lineWidth="42" :inactiveStyle="{fontSize:'32rpx'}" :activeStyle="{color: '#303133',fontWeight: 'bold', transform: 'scale(1.01)'}"></u-tabs>
</view> </view>
<view class="listenList" v-if="bookList.length > 0"> <view class="listenList" v-if="bookList.length > 0">
<view class="wrap" v-if="contentShow == 0"> <view class="wrap" v-if="contentShow == 1">
<u-row gutter="16" justify="flex-start"> <u-row gutter="16" justify="flex-start">
<u-col span="6" v-for="(item,index) in bookList" :key="index"> <u-col span="6" v-for="(item,index) in bookList" :key="index">
<view >
<view class="flexbox listenItem"> <view class="flexbox listenItem">
<view class="info"> <view class="info">
<view class="videoBox demo-layout bg-purple" @click="goToListenFree(item)"> <view class="videoBox demo-layout bg-purple" @click="goToListenFree(item)">
@@ -25,11 +49,11 @@
</view> </view>
<view class="btns"> <view class="btns">
<view class="item flexbox" @click=""> <!-- <view class="item flexbox" @click="">
<!-- <u-icon name="bookmark" color="#55aaff" size="24"></u-icon> --> <u-icon name="bookmark" color="#55aaff" size="24"></u-icon>
<image src="../../static/icon/tu1.png" mode="aspectFit"></image> <image src="../../static/icon/tu1.png" mode="aspectFit"></image>
<text > </text> <text > </text>
</view> </view> -->
<view class="item flexbox" @click="goToListenFree(item)"> <view class="item flexbox" @click="goToListenFree(item)">
<!-- <u-icon name="volume" color="#71d5a1" size="24"></u-icon> --> <!-- <u-icon name="volume" color="#71d5a1" size="24"></u-icon> -->
<image src="../../static/icon/tu2.png" mode="aspectFit"></image> <image src="../../static/icon/tu2.png" mode="aspectFit"></image>
@@ -42,35 +66,36 @@
</view> </view>
</view> </view>
</view> </view>
<view class="bookName">{{item.bookName}}</view> <view class="bookName">{{item.bookName}}</view>
</view>
</u-col> </u-col>
</u-row> </u-row>
</view> </view>
<view class="wrap" v-if="contentShow == 1"> <view class="wrap" v-if="contentShow == 2">
<u-row gutter="16" justify="flex-start"> <u-row gutter="16" justify="flex-start">
<u-col span="6" v-for="(item,index) in tjBookLIst" :key="index"> <u-col span="6" v-for="(item,index) in tjBookLIst" :key="index">
<view class="flexbox listenItem"> <view class="flexbox listenItem">
<view class="info"> <view class="info">
<view class="videoBox demo-layout bg-purple" @click="goDetail(item)"> <view class="videoBox demo-layout bg-purple" @click="goDetail(item.product)">
<image :src="item.productImages" mode="scaleToFill" ></image> <image :src="item.product.productImages" mode="scaleToFill" ></image>
</view> </view>
</view> </view>
<view class="btns"> <view class="btns">
<view class="item flexbox" @click=""> <view class="item flexbox" @click="goDetail(item.product)">
<image src="../../static/icon/tu1.png" mode="aspectFit"></image> <image src="../../static/icon/tu1.png" mode="aspectFit"></image>
<text> </text> <text> </text>
</view> </view>
<view class="item flexbox" @click="goToListen(item)"> <view class="item flexbox" @click="goToListen(item.product)">
<image src="../../static/icon/tu2.png" mode="aspectFit"></image> <image src="../../static/icon/tu2.png" mode="aspectFit"></image>
<text> </text> <text> </text>
</view> </view>
<view class="item flexbox" @click="wgGoPingshu(item)"> <view class="item flexbox" @click="wgGoPingshu(item.product)">
<image src="../../static/icon/tu3.png" mode="aspectFit"></image> <image src="../../static/icon/tu3.png" mode="aspectFit"></image>
<text> </text> <text> </text>
</view> </view>
</view> </view>
</view> </view>
<view class="bookName">{{item.productName}}</view> <view class="bookName">{{item.product.productName}}</view>
</u-col> </u-col>
</u-row> </u-row>
</view> </view>
@@ -100,11 +125,16 @@
export default { export default {
data() { data() {
return { return {
list3: [
// '../../static/icon/home_ban_1.jpg',
'../../static/icon/home_ban_2.jpg',
'../../static/icon/home_ban_3.jpg',
],
showEbook:false, showEbook:false,
playData:{}, playData:{},
loadingNow : false, loadingNow : false,
bookList:[], bookList:[],
contentShow:0, contentShow:1,
page:1, // 页码 page:1, // 页码
status: 3, status: 3,
ygtotalPage:1, ygtotalPage:1,
@@ -127,13 +157,13 @@
onPullDownRefresh() { onPullDownRefresh() {
console.log('下拉刷新了') console.log('下拉刷新了')
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
if(this.contentShow == 0){ if(this.contentShow == 1){
this.page=1, // 页码 // this.page=1, // 页码
this.bookList = [] this.bookList = []
this.getfreeBook() this.getfreeBook()
} }
else if(this.contentShow == 1){ else if(this.contentShow == 2){
this.tjPage=1, // 页码 // this.tjPage=1, // 页码
this.tjBookLIst = [] this.tjBookLIst = []
this.getListDate() this.getListDate()
} }
@@ -142,33 +172,33 @@
this.loadingNow = true this.loadingNow = true
console.log('到底了') console.log('到底了')
if(this.contentShow == 0){ // if(this.contentShow == 1){
//console.log(this.page , this.ygtotalPage) // //console.log(this.page , this.ygtotalPage)
if(this.page < this.ygtotalPage){ // if(this.page < this.ygtotalPage){
this.page++ // this.page++
console.log('加载',this.page) // console.log('加载',this.page)
this.status = 0 // this.status = 0
this.getfreeBook() // this.getfreeBook()
}else{ // }else{
this.status = 1 // this.status = 1
console.log('加载完成了',this.page) // console.log('加载完成了',this.page)
return // return
} // }
}else if(this.contentShow == 1){ // }else if(this.contentShow == 2){
if(this.tjPage < this.tjTotalPage){ // if(this.tjPage < this.tjTotalPage){
this.tjPage++ // this.tjPage++
console.log('加载',this.tjPage) // console.log('加载',this.tjPage)
this.status = 0 // this.status = 0
this.getListDate() // this.getListDate()
}else{ // }else{
this.status = 1 // this.status = 1
console.log('加载完成了',this.tjPage) // console.log('加载完成了',this.tjPage)
return // return
} // }
} // }
}, },
components:{ components:{
musicPlay musicPlay
@@ -177,36 +207,24 @@
...mapState(['userInfo']) ...mapState(['userInfo'])
}, },
methods: { methods: {
setData(e){
this.contentShow = e
},
// 未购买图书,评书跳转 // 未购买图书,评书跳转
wgGoPingshu(item){ wgGoPingshu(item){
console.log('未购买评书',item) console.log('未购买评书',item)
if(item.bookId == null || item.bookId.length <= 0){
//uni.showModal()
uni.showModal({
title: '提示',
showCancel:false,
content: '当前未关联图书信息,请联系联系管理员',
success: function (res) {
if (res.confirm) {
console.log('好的');
}
}
});
}else{
uni.navigateTo({ uni.navigateTo({
url: '../comments/comments?bookid='+item.bookId[0], url: '../comments/comments?bookid='+item.bookId,
// url:'../bookShop/commodityDetail' // url:'../bookShop/commodityDetail'
}); });
}
}, },
// 跳转到评书 // 跳转到评书
goPingshu(val){ goPingshu(val){
console.log('评书',val) console.log('评书',val)
uni.navigateTo({ uni.navigateTo({
url: '../comments/comments?bookid='+val, url: '../comments/comments?bookid='+val,
// url:'../bookShop/commodityDetail'
}); });
}, },
contentButtonClick(e){ contentButtonClick(e){
@@ -214,6 +232,7 @@
}, },
// 获取已购买书籍 // 获取已购买书籍
getfreeBook(){ getfreeBook(){
console.log('获取已购买书籍')
this.$http this.$http
.post('book/userebookbuy/buylist', { .post('book/userebookbuy/buylist', {
// .post('book/buyorderdetail/querybuy', { // .post('book/buyorderdetail/querybuy', {
@@ -224,8 +243,16 @@
.then(res => { .then(res => {
if(res.code == 0){ if(res.code == 0){
this.ygtotalPage = res.page.totalPage // this.ygtotalPage = res.page.totalPage
this.bookList = this.bookList.concat(res.page.list) //var arr = res.page
res.page.forEach(item => {
if(item.canListen){
this.bookList.push(item)
}
})
// console.log(this.bookList,'arr')
//this.bookList = arr
// this.bookList = this.bookList.concat(res.page.list)
console.log(res,'已购买') console.log(res,'已购买')
this.status = 3 this.status = 3
} }
@@ -235,6 +262,7 @@
// 获取推荐图书(未购买) // 获取推荐图书(未购买)
getListDate(){ getListDate(){
console.log('获取推荐图书(未购买)')
this.loadingNow = false this.loadingNow = false
// 获取书架列表 // 获取书架列表
this.$http this.$http
@@ -244,63 +272,52 @@
'page':this.tjPage 'page':this.tjPage
}) })
.then(res => { .then(res => {
console.log(res) console.log(res,'获取推荐图书(未购买)')
if(res.code == 0){ if(res.code == 0){
this.tjTotalPage = res.pages.totalPage // this.tjTotalPage = res.pages.totalPage
var arr = [] var arr = []
if(res.pages.list.length > 0){ if(res.pages.length > 0){
for (var i=0; i<res.pages.list.length; i++ ) { // for (var i=0; i<res.pages.list.length; i++ ) {
var booidArr = [] // var booidArr = []
if(res.pages.list[i].bookId != null){ // if(res.pages.list[i].bookId != null){
booidArr = res.pages.list[i].bookId.split(',') // booidArr = res.pages.list[i].bookId.split(',')
//res.pages.list[i].bookId = booidArr // //res.pages.list[i].bookId = booidArr
res.pages.list[i].bookId = booidArr // res.pages.list[i].bookId = booidArr
}else{ // }else{
res.pages.list[i].bookId = [] // res.pages.list[i].bookId = []
} // }
} // }
console.log(res.pages.list,'res.pages.list') //console.log(res.pages,'res.pages.list')
// var arr = res.pages.list // var arr = res.pages.list
this.tjBookLIst = this.tjBookLIst.concat(res.pages.list) this.tjBookLIst = res.pages
// console.log(res) // this.tjBookLIst = this.tjBookLIst.concat(res.pages.list)
// console.log(this.tjBookLIst[0])
this.status = 3 this.status = 3
} } } }
}); });
}, },
// 跳转详情页 // 跳转详情页
goDetail(item) { goDetail(item) {
console.log(item,'goDetail-----') console.log(item,'goDetail-----')
uni.navigateTo({ uni.navigateTo({
url: '../bookShop/commodityDetail?id=' + item.productId url: '../bookShop/commodityDetail?id=' + item.productId
}); });
}, },
goToListen(item){ goToListen(item){
if(item.bookId == null || item.bookId.length <= 0){ console.log(item,'item')
//uni.showModal()
uni.showModal({
title: '提示',
showCancel:false,
content: '当前图书暂不支持试听',
success: function (res) {
if (res.confirm) {
console.log('好的');
}
}
});
}else{
uni.navigateTo({ uni.navigateTo({
url: "../listen/listen?bookid="+item.bookId[0] url: "../listen/listen?bookid="+item.bookId
}); });
}
}, },
// 跳转到听书详情 // 跳转到听书详情
goToListenFree(item){ goToListenFree(item){
console.log(item,'item') // console.log(item,'item')
uni.navigateTo({ uni.navigateTo({
// url: "./musicbg?bookid="+item.bookid+"&fengImg="+item.image // 台播放版本 url: "../listen/listen?bookid="+item.bookId+"&fengImg="+item.image // 台播放版本
url: "../listen/listen?bookid="+item.bookId+"&fengImg="+item.image // 前台播放版本
// url: "./bgMusix"
}); });
}, },
// 跳转11 // 跳转11
@@ -315,6 +332,22 @@
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/style/mixin.scss'; @import '@/style/mixin.scss';
.home_lunbo {
margin: 40rpx 30rpx 0 30rpx;
}
.mytabs{
// background: url('@/static/icon/bgtushu.png') no-repeat left top;
height:110rpx ; margin-bottom: 50rpx;
.item{
border-radius: 10rpx;background-color: #adb6b7; width: 48%; margin: 0 10rpx; text-align: center; color:#fff ; font-size: 36rpx; line-height:110rpx ;
}
.item.active{
background-color: #73837b;
}
.item1{
background-color: #adb6b7;
}
}
.listenItem{ .listenItem{
.btns{margin-top: 60rpx; margin-left: 20rpx; font-size: 34rpx; justify-content: space-between; .btns{margin-top: 60rpx; margin-left: 20rpx; font-size: 34rpx; justify-content: space-between;
.item{ margin-bottom:30rpx; .item{ margin-bottom:30rpx;
@@ -398,35 +431,33 @@
} }
} }
.home_bg { .home_bg {
background-image: url('@/static/icon/home_bg.jpg'); background-image: url('@/static/icon/home_bg1.jpg');
background-position: center center; background-position: center center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
padding: 100rpx 0 40rpx 0; padding: 100rpx 20rpx 40rpx 20rpx;
position: relative; position: relative;
height: 400rpx; margin-bottom: 130rpx;
.icon_hua_1 { .icon_hua_1 {
margin: 0 auto; // margin: 0 auto;
width: 150rpx; width: 150rpx;
height: 150rpx; height: 150rpx;
} }
.icon_hua{width: 150rpx; display: block;}
.search_box { .search_box { margin-top: 20rpx; align-items: center;
width: 90%; width: calc(100% - 300rpx);
height: 64upx;
background-color: #fff; .search{height: 80upx;
border-radius: 32upx; display: flex;
display: flex; width: 100%;
align-items: center; align-items: center;
padding: 0upx 40upx; padding: 0upx 40upx;
position: absolute; background-color: #fff;
margin-left: -46%; border-radius: 20upx;
left: 50%; box-shadow: 0 0px 10px 1px #54a96633;
bottom: -40rpx; }
box-shadow: 0 0px 10px 1px #54a96633;
.prompt { .prompt {
color: #cccccc; color: #838383; font-size: 24rpx;
} }
@@ -435,10 +466,14 @@
background-position: center center; background-position: center center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
width: 29upx; width:36upx;
height: 28upx; height: 36upx;
margin-right: 20upx; margin-right: 20upx;
} }
} }
.searBtn{
width: 80rpx; align-items: center;
font-size: 30rpx; color: #fff;
}
} }
</style> </style>

View File

@@ -17,32 +17,25 @@
<view class="wrap" v-if="contentShow == 0"> <view class="wrap" v-if="contentShow == 0">
<u-row gutter="16" justify="flex-start"> <u-row gutter="16" justify="flex-start">
<u-col span="4" v-for="(item,index) in bookList" :key="index"> <u-col span="4" v-for="(item,index) in bookList" :key="index">
<view>
<view class="videoBox demo-layout bg-purple" @click="goToListenFree(item)"> <view class="videoBox demo-layout bg-purple" @click="goToListenFree(item)">
<image :src="item.image" mode="scaleToFill" ></image> <image v-if="item.image != ''" :src="item.image" mode="scaleToFill" ></image>
<u-icon class="playButton" name="play-circle" color="#54a966" size="28"></u-icon> <image v-else src="../../static/icon/wufeng.jpg" mode="scaleToFill" ></image>
<!-- <u-icon class="playButton" name="play-circle" color="#54a966" size="40"></u-icon> -->
</view>
<text class="bookName">{{item.bookName}}</text>
</view> </view>
<text class="bookName">{{item.bookName}}</text>
<!-- <view class="btns flexbox">
<view class="item flexbox" @click="goToListenFree(item)">
<u-icon name="volume" color="#71d5a1" size="24"></u-icon>
<text> </text>
</view>
<view class="item flexbox" @click="goPingshu(item.bookId)">
<u-icon name="chat" color="#fcbd71" size="24"></u-icon>
<text> </text>
</view>
</view> -->
</u-col> </u-col>
</u-row> </u-row>
</view> </view>
<view class="wrap" v-if="contentShow == 1"> <view class="wrap" v-if="contentShow == 1">
<u-row gutter="16" justify="flex-start"> <u-row gutter="16" justify="flex-start">
<u-col span="4" v-for="(item,index) in tjBookLIst" :key="index"> <u-col span="4" v-for="(item,index) in tjBookLIst" :key="index">
<view class="videoBox demo-layout bg-purple" @click="goDetail(item)"> <view class="videoBox demo-layout bg-purple" @click="goDetail(item.product)">
<image :src="item.productImages" mode="scaleToFill" ></image> <image :src="item.product.productImages" mode="scaleToFill" ></image>
<u-icon class="playButton" name="play-circle" color="#54a966" size="28"></u-icon> <!-- <u-icon class="playButton" name="play-circle" color="#54a966" size="40"></u-icon> -->
</view> </view>
<text class="bookName">{{item.productName}}</text> <text class="bookName">{{item.product.productName}}</text>
<!-- <view class="btns flexbox"> <!-- <view class="btns flexbox">
<view class="item flexbox" @click="goToListen(item)"> <view class="item flexbox" @click="goToListen(item)">
<u-icon name="volume" color="#71d5a1" size="24"></u-icon> <u-icon name="volume" color="#71d5a1" size="24"></u-icon>
@@ -108,12 +101,12 @@
console.log('下拉刷新了') console.log('下拉刷新了')
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
if(this.contentShow == 0){ if(this.contentShow == 0){
this.page=1, // 页码 // this.page=1, // 页码
this.bookList = [] this.bookList = []
this.getfreeBook() this.getfreeBook()
} }
else if(this.contentShow == 1){ else if(this.contentShow == 1){
this.tjPage=1, // 页码 // this.tjPage=1, // 页码
this.tjBookLIst = [] this.tjBookLIst = []
this.getListDate() this.getListDate()
} }
@@ -122,21 +115,23 @@
this.loadingNow = true this.loadingNow = true
console.log('到底了') console.log('到底了')
if(this.contentShow == 0){ // if(this.contentShow == 0){
//console.log(this.page , this.ygtotalPage) // //console.log(this.page , this.ygtotalPage)
if(this.page < this.ygtotalPage){ // if(this.page < this.ygtotalPage){
this.page++ // this.page++
console.log('加载',this.page) // console.log('加载',this.page)
this.status = 0 // this.status = 0
this.getfreeBook() // this.getfreeBook()
}else{ // }else{
this.status = 1 // this.status = 1
console.log('加载完成了',this.page) // console.log('加载完成了',this.page)
return // return
} // }
}else if(this.contentShow == 1){ // }
if(this.contentShow == 1){
if(this.tjPage < this.tjTotalPage){ if(this.tjPage < this.tjTotalPage){
this.tjPage++ this.tjPage++
console.log('加载',this.tjPage) console.log('加载',this.tjPage)
@@ -204,8 +199,14 @@
.then(res => { .then(res => {
if(res.code == 0){ if(res.code == 0){
this.ygtotalPage = res.page.totalPage // this.ygtotalPage = res.page.totalPage
this.bookList = this.bookList.concat(res.page.list)
res.page.forEach(item => {
if(item.canListen){
this.bookList.push(item)
}
})
// this.bookList = = this.bookList.concat(res.page.list)
console.log(res,'已购买') console.log(res,'已购买')
this.status = 3 this.status = 3
} }
@@ -220,26 +221,24 @@
this.$http this.$http
.post('book/shopproduct/booklist', { .post('book/shopproduct/booklist', {
'userId': this.userInfo.id, 'userId': this.userInfo.id,
'limit':9, // 'limit':9,
'page':this.tjPage // 'page':this.tjPage
}) })
.then(res => { .then(res => {
console.log(res) console.log(res)
if(res.code == 0){ if(res.code == 0){
this.tjTotalPage = res.pages.totalPage // this.tjTotalPage = res.pages.totalPage
var arr = [] var arr = []
if(res.pages.list.length > 0){ if(res.pages.length > 0){
for (var i=0; i<res.pages.list.length; i++ ) { // for (var i=0; i<res.pages.length; i++ ) {
var booidArr = [] // var booidArr = []
if(res.pages.list[i].bookId != null){ // if(res.pages[i].product.bookId != null){
booidArr = res.pages.list[i].bookId.split(',') // booidArr = res.pages[i].product.bookId.split(',')
//res.pages.list[i].bookId = booidArr // res.pages[i].product.bookId = booidArr
// console.log(booidArr,'booidArr') // }else{
res.pages.list[i].bookId = booidArr // res.pages[i].product.bookId = []
}else{ // }
res.pages.list[i].bookId = [] // }
}
}
// res.pages.list.map((item) => { // res.pages.list.map((item) => {
// var ids = item.bookId.split(",") // var ids = item.bookId.split(",")
@@ -253,10 +252,12 @@
// }else{ // }else{
// arr = [] // arr = []
// } // }
console.log(res.pages.list,'res.pages.list') // console.log(res.pages.list,'res.pages.list')
this.tjBookLIst = res.pages
// var arr = res.pages.list // var arr = res.pages.list
this.tjBookLIst = this.tjBookLIst.concat(res.pages.list) // this.tjBookLIst = this.tjBookLIst.concat(res.pages)
// console.log(res) console.log(this.tjBookLIst[0].product,'this.tjBookLIst')
this.status = 3 this.status = 3
} } } }
@@ -319,7 +320,9 @@
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: 30rpx; color: #333; padding: 10rpx 0; font-size: 30rpx; color: #333; padding: 10rpx 0;
} }
.videoBox{position: relative;} .videoBox{position: relative;
image{height: 290rpx;}
}
.playButton{position: absolute; z-index: 1; right: 4px; bottom: 4px; padding: 5px; border-radius: 100%; } .playButton{position: absolute; z-index: 1; right: 4px; bottom: 4px; padding: 5px; border-radius: 100%; }
uni-image { uni-image {
@@ -327,7 +330,7 @@
height: 350rpx; height: 350rpx;
} }
.u-row{flex-wrap: wrap;} .u-row{flex-wrap: wrap;}
.u-col{overflow: hidden; height: 250px; margin-bottom: 30rpx; } .u-col{overflow: hidden; margin-bottom:20rpx; }
.listenList{padding: 10rpx; box-sizing: border-box; width: calc(100% - 10rpx);} .listenList{padding: 10rpx; box-sizing: border-box; width: calc(100% - 10rpx);}
.flexbox{display: flex;} .flexbox{display: flex;}
.scroll-Y { .scroll-Y {

View File

@@ -9,7 +9,9 @@
<view class="book_neir"> <view class="book_neir">
<view class="flexbox info"> <view class="flexbox info">
<view class="item"> <view class="item">
<image class="bn_img" :src="bookInfo.images" <image class="bn_img" v-if="bookInfo.images != ''" :src="bookInfo.images"
mode="widthFix"></image>
<image class="bn_img" style="border:1px solid #eee" v-else src="../../static/icon/wufeng.jpg"
mode="widthFix"></image> mode="widthFix"></image>
</view> </view>
<!-- <img :src="bookInfo.images" class="bn_img"> --> <!-- <img :src="bookInfo.images" class="bn_img"> -->
@@ -115,7 +117,10 @@
playid:null, // 正在播放的章节id playid:null, // 正在播放的章节id
playchapName:'', // 正在播放的章节名称 playchapName:'', // 正在播放的章节名称
playIndex:null, // 正在播放的序号值 playIndex:null, // 正在播放的序号值
onlineH:{}, // 线上的历史听书 onlineH:{ // 线上的历史听书
playIndex:null, // 存储的播放index
time:0, // 存储的播放秒数
},
currentTime:{ currentTime:{
time:0, time:0,
flag:'' flag:''
@@ -200,7 +205,7 @@
console.log(this.muteBgMusic,this.muteBgMusic?'已关闭音乐####':'已开启音乐####'); console.log(this.muteBgMusic,this.muteBgMusic?'已关闭音乐####':'已开启音乐####');
}, },
// 获取线上听书进度 // 获取线上听书进度
getListenRate(val,op){ getListenRate(){
let data = { let data = {
bookId: this.bookid, bookId: this.bookid,
userId: this.userInfo.id, userId: this.userInfo.id,
@@ -216,46 +221,42 @@
console.log(res,'历史记录') console.log(res,'历史记录')
if(res.readRate.chapterId){ if(res.readRate.chapterId){
var item = res.readRate var item = res.readRate
if(this.$bgm._options.src != '' && res.readRate.chapterId == this.userInfo.playingInfo.chapterId && res.readRate.bookId == this.userInfo.playingInfo.bookid ){
// console.log(this.$bgm)
if(this.$bgm.playing){
console.log('线上存储进度是同一条数据,不做处理')
}else{ // 暂停状态下
this.$bgm.play()
}
return false
}
this.onlineH.time = item.precent
// 有听书进度时 // 有听书进度时
this.onlineH.playIndex = bgm.musicList.findIndex(function(info){ this.onlineH.playIndex = this.libLIst.findIndex(function(info){
// console.log(info,'info') // console.log(info,'info')
if(item.chapterId == info.chapterId && item.bookId == info.bookid ){ if(item.chapterId == info.chapterId && item.bookId == info.bookid ){
return info; return info;
} }
}) })
//store.commit('setUserInfo',{'playingInfo':bgm.musicList[bgm.playIndex] }) console.log('线上的播放index是',this.onlineH.playIndex)
console.log('线上的播放index是',this.onlineH.playIndex)
}else{ }else{
// 没有听书进度 // 没有听书进度
this.onlineH.playIndex = 0
this.onlineH.time = 0
} }
console.log('到这')
this.$music.setList(this.libLIst,'autoPlay',this.onlineH.playIndex, this.onlineH.time)
}) })
}, },
addMusicList(){ addMusicList(){
if (this.userInfo.playFlag) { this.getListenRate()
// 暂停
// this.$music.playBgm({mute:true})
// this.$bgm.pause()
uni.showToast({
title:'已经在播放音频',
icon:'none'
})
} else {
// 播放
// this.$music.playBgm({mute:false})
if(this.$bgm._options.src == ''){
this.$music.playBgm({mute:false})
}else{
this.$bgm.play()
}
}
// this.playData = { // this.playData = {
// 'myList' : this.libLIst, // 'myList' : this.libLIst,
// // 'fengImg' : this.fengImg, // // 'fengImg' : this.fengImg,
// } // }
// 显示播放组件 // 显示播放组件
this.setUserInfo({'playVisible':true}) this.setUserInfo({'playVisible':true})
uni.setStorage({ uni.setStorage({
key: 'playVisible', key: 'playVisible',
data: true, data: true,
@@ -268,10 +269,8 @@
}, },
// 播放单个音频 // 播放单个音频
listenOne(item,index){ listenOne(item,index){
console.log('点击了',index)
console.log('点击了',index)
if(this.libLIst.length > 0){ if(this.libLIst.length > 0){
this.setUserInfo({'playIndex': index}) this.setUserInfo({'playIndex': index})
this.$music.setList(this.libLIst,'autoPlay',index) this.$music.setList(this.libLIst,'autoPlay',index)
@@ -330,48 +329,7 @@
url: '../eBook/bookMessage?Id=' + id + '&typ=' + e url: '../eBook/bookMessage?Id=' + id + '&typ=' + e
}); });
}, },
// 获取听书进度
getListenRate(){
// this.forceRefresh = false
let data = {
bookId: this.bookid,
userId: this.userInfo.id,
}
$http.request({
url: "book/listening/getReadRate",
method: "POST", // POST、GET、PUT、DELETE具体说明查看官方文档
data,
header: { //默认 无 说明:请求头
'Content-Type': 'application/json'
},
}).then(res => {
console.log(res,'历史记录')
if(res.readRate.chapterId){ // 有听书进度时
this.playid = res.readRate.chapterId
this.currentTime.time = res.readRate.precent
this.currentTime.flag = 'init'
// this.forceRefresh = true
for (var i =0; i<this.libLIst.length; i++) {
if(res.readRate.chapterId == this.libLIst[i].chapterId){
this.playIndex = i
}
}
// this.playIndex = res.readRate.id - 1
// console.log('有内容',this.playIndex)
this.playIndex >= this.libLIst.length - 1 ? this.jia = true : this.jia = false
this.playIndex > 0 ? this.jian = true : this.jian = false
// this.firstListen()
}else{ // 没有听书进度时
// this.listen(this.libLIst[0],0)
}
})
},
// 第一次加载音乐播放器 // 第一次加载音乐播放器
firstListen(){ firstListen(){
this.forceRefresh = false this.forceRefresh = false

View File

@@ -1,11 +1,23 @@
<template> <template>
<view style="font-size: 28upx;"> <view style="font-size: 28upx;">
<!-- <z-nav-bar backState="2000" title="首页"></z-nav-bar> --> <!-- <z-nav-bar backState="2000" title="首页"></z-nav-bar> -->
<view class="home_bg" > <view class="home_bg">
<image src="../../static/icon/home_icon_1.png" mode="aspectFit" class="icon_hua_1"></image> <view class="flexbox" style=" justify-content: space-between; ">
<view v-if="showEbook" class="search_box" @click="onPageJump('./searchFor')"> <view class="icon_hua">
<text class="icon_search"></text> <image src="../../static/icon/home_icon_3.png" mode="aspectFit" class="icon_hua_1"></image>
<text class="prompt">搜索...</text> </view>
<view class="search_box flexbox" @click="onPageJump('./searchFor')">
<view class="search">
<text class="icon_search"></text>
<text class="prompt">请输入想要搜索的书名</text>
</view>
</view>
<view class="searBtn flexbox">
<text>搜索</text>
</view>
</view>
<view class="home_lunbo">
<u-swiper :list="list3" indicator indicatorMode="line" circular style="height: 180rpx;"></u-swiper>
</view> </view>
</view> </view>
<!-- <view class="home_nar" v-if="showEbook"> --> <!-- <view class="home_nar" v-if="showEbook"> -->
@@ -21,10 +33,10 @@
</view> </view>
<!-- <view class="hn_cl_tit" @click="onPageJump('../bookShop/bookShopIndex')"> --> <!-- <view class="hn_cl_tit" @click="onPageJump('../bookShop/bookShopIndex')"> -->
<view class="hn_cl_tit shuping" @click="onTabJump()"> <!-- <view class="hn_cl_tit shuping" @click="onTabJump()">
<image src="../../static/icon/home3.png" mode="aspectFit"></image> <image src="../../static/icon/home3.png" mode="aspectFit"></image>
<text>书评</text> <text>书评</text>
</view> </view> -->
<view class="hn_cl_tit chaoshi" @click="onPageJump('../bookShop/classify')"> <view class="hn_cl_tit chaoshi" @click="onPageJump('../bookShop/classify')">
<image src="../../static/icon/home4.png" mode="aspectFit"></image> <image src="../../static/icon/home4.png" mode="aspectFit"></image>
@@ -32,9 +44,9 @@
</view> </view>
</view> </view>
<view class="home_lunbo"> <!-- <view class="home_lunbo">
<u-swiper :list="list3" indicator indicatorMode="line" circular style="height: 180rpx;"></u-swiper> <u-swiper :list="list3" indicator indicatorMode="line" circular style="height: 180rpx;"></u-swiper>
</view> </view> -->
<view class="home_shujia" v-if="showEbook"> <view class="home_shujia" v-if="showEbook">
<view class="hn_sj" @click="onTabJump('./bookshelf')"> <view class="hn_sj" @click="onTabJump('./bookshelf')">
@@ -89,9 +101,21 @@
<view class="head_line" > <view class="head_line" >
<b></b> <b></b>
<text>新书上市</text> <text>新书上市</text>
<i @click="onBookMore('New')">查看更多 ></i> <!-- <i @click="onBookMore('New')">查看更多 ></i> -->
</view> </view>
<view class="newBook">
<scroll-view class="scroll-view_H " scroll-x="true" scroll-left="10">
<view :class="['item']" v-for="(item,index) in newBookList" :key="index">
<view class="videoBox" @click="goDetail(item.productId)">
<image v-if="item.productImages != ''" :src="item.productImages" mode="scaleToFill"></image>
<image v-else src="../../static/icon/wufeng.jpg" mode="scaleToFill"></image>
</view>
<text class="bookName">{{item.productName}}</text>
</view>
</scroll-view>
</view>
<view class="home_xinshu" v-if="showEbook"> <view class="home_xinshu" v-if="showEbook">
<view v-for="(item, index) in xinsList" @click="onBookJump(item)" v-if="index<3" class="hx_list"> <view v-for="(item, index) in xinsList" @click="onBookJump(item)" v-if="index<3" class="hx_list">
<image :src="item.image"></image> <image :src="item.image"></image>
@@ -214,6 +238,7 @@
transaction: { // 成功回调 transaction: { // 成功回调
}, },
scrollLeft:0,
maxTimes:1, // 轮询最大次数 maxTimes:1, // 轮询最大次数
ComplateRequestInterval:null, // 轮询定时器 ComplateRequestInterval:null, // 轮询定时器
checking:false, // 正在检测 checking:false, // 正在检测
@@ -233,6 +258,7 @@
bgiStyle: { bgiStyle: {
background: '#fff' background: '#fff'
}, },
newBookList:[],
iconStyle: { iconStyle: {
fontSize: '40rpx', fontSize: '40rpx',
fontWeight: 'bold', fontWeight: 'bold',
@@ -265,7 +291,7 @@
onPullDownRefresh() { onPullDownRefresh() {
this.getData() this.getData()
uni.stopPullDownRefresh() uni.stopPullDownRefresh()
this.requestIapOrder() this.requestIapOrder()
}, },
@@ -291,6 +317,19 @@
//方法 //方法
methods: { methods: {
...mapMutations(['setUserInfo']), ...mapMutations(['setUserInfo']),
// 新书上市
getNewBook(){
this.$http
.post('book/shopproduct/getNewBook',{
'limit': 10,
'page':1
})
.then(res => {
console.log(res,'xinshu')
this.newBookList = res.page.list
});
},
// 检测未完成订单 // 检测未完成订单
requestIapOrder(){ requestIapOrder(){
console.log('检测支付环境...') console.log('检测支付环境...')
@@ -479,6 +518,8 @@
console.log(res.page.list,'首页商品') console.log(res.page.list,'首页商品')
this.goodsList = res.page.list this.goodsList = res.page.list
}) })
this.getNewBook()
}, },
// 跳转 // 跳转
@@ -519,7 +560,7 @@
url: '../bookShop/commodityDetail?id=' + id url: '../bookShop/commodityDetail?id=' + id
}); });
}, },
// 列表跳页 // 列表跳页
onShopMore(e) { onShopMore(e) {
uni.navigateTo({ uni.navigateTo({
@@ -542,7 +583,24 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/style/mixin.scss'; @import '@/style/mixin.scss';
.newBook{margin-top: 20rpx;}
.scroll-view_H{background-color: #fff;white-space: nowrap;
width: 100%; padding:10rpx ; }
.scroll-view_H{
.item { padding: 10rpx; overflow: hidden; display: inline-block;
width: 180rpx !important; margin-right: 20rpx; border-radius: 10rpx;
.videoBox{
image{display: block; width:150rpx;
height: 170rpx;
}
}
.bookName{display: block; margin-top: 20rpx; color: #666; font-size: 24rpx; white-space: nowrap;
overflow-x: hidden; overflow: hidden;
text-overflow: ellipsis;}
}
// .item.active{margin-right: 20rpx; border: 1px solid #55aa00; border-radius: 10rpx;}
}
.flexbox{display: flex;}
.head_line { .head_line {
margin: 50rpx 0 0 0; margin: 50rpx 0 0 0;
@@ -571,50 +629,51 @@
} }
.home_bg { .home_bg {
background-image: url('@/static/icon/home_bg.jpg'); background-image: url('@/static/icon/home_bg1.jpg');
background-position: center center; background-position: center center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
padding: 100rpx 0 40rpx 0; padding: 100rpx 20rpx 40rpx 20rpx;
position: relative; position: relative;
height: 400rpx; margin-bottom: 130rpx;
.icon_hua_1 { .icon_hua_1 {
margin: 0 auto; // margin: 0 auto;
width: 150rpx; width: 150rpx;
height: 150rpx; height: 150rpx;
} }
.icon_hua{width: 150rpx; display: block;}
.search_box { .search_box { margin-top: 20rpx; align-items: center;
width: 90%; width: calc(100% - 300rpx);
height: 64upx;
background-color: #fff; .search{height: 80upx;
border-radius: 32upx; display: flex;
display: flex; width: 100%;
align-items: center; align-items: center;
padding: 0upx 40upx; padding: 0upx 40upx;
position: absolute; background-color: #fff;
margin-left: -46%; border-radius: 20upx;
left: 50%; box-shadow: 0 0px 10px 1px #54a96633;
bottom: -30rpx;
box-shadow: 0 0px 10px 1px #54a96633;
.prompt {
color: #cccccc;
} }
.prompt {
color: #838383; font-size: 24rpx;
}
.icon_search { .icon_search {
background-image: url('@/static/icon/map_ic_search.png'); background-image: url('@/static/icon/map_ic_search.png');
background-position: center center; background-position: center center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
width: 29upx; width:36upx;
height: 28upx; height: 36upx;
margin-right: 20upx; margin-right: 20upx;
} }
} }
} .searBtn{
width: 80rpx; align-items: center;
font-size: 30rpx; color: #fff;
}
}
.home_nar { padding-bottom: 20rpx; .home_nar { padding-bottom: 20rpx;
margin: 30rpx 20rpx; justify-content: space-between; margin: 30rpx 20rpx; justify-content: space-between;
display: flex; display: flex;
@@ -626,7 +685,8 @@
// .shuping{ background-color: #d6ffda; border: 2px solid #bae9bf;} // .shuping{ background-color: #d6ffda; border: 2px solid #bae9bf;}
// .shuguan{ background-color:#e3f9f9 ; border: 2px solid #d7eced; } // .shuguan{ background-color:#e3f9f9 ; border: 2px solid #d7eced; }
.hn_cl_tit { padding-bottom: 10rpx; .hn_cl_tit { padding-bottom: 10rpx;
width: 23%; // width: 23%;
width: 31%;
text-align: center; text-align: center;
border-radius: 20rpx ; padding-top: 10rpx; border-radius: 20rpx ; padding-top: 10rpx;
// line-height: 110upx; // line-height: 110upx;
@@ -638,9 +698,9 @@
height:110upx; height:110upx;
display: block; display: block;
margin: 0 auto; margin: 0 auto;
margin: 0 20rpx; // margin: 0 20rpx;
} }
text{ display:block; margin-top: 10px; font-size: 36rpx; color: #000; font-weight:blod;} text{ display:block; text-align: center; margin-top: 10px; font-size: 36rpx; color: #000; font-weight:blod;}
} }

View File

@@ -18,22 +18,22 @@
</view> </view>
<br clear="both"> <br clear="both">
</view> </view>
<view class="now_vip" v-if="userMes.vip==0"> <!-- <view class="now_vip" v-if="userMes.vip==0">
<text> <text>
<image src="../../static/icon/mine_p.png" style="height: 44rpx;"></image> <image src="../../static/icon/mine_p.png" style="height: 44rpx;"></image>
开通会员畅享海量内容 开通会员畅享海量内容
</text> </text>
<b class="kt_btn" @click="onPageJump('./opeVip')">开通VIP</b> <b class="kt_btn" @click="onPageJump('./opeVip')">开通VIP</b>
</view> </view> -->
<view class="now_vip" v-if="userMes.vip==1"> <!-- <view class="now_vip" v-if="userMes.vip==1">
<text> <text>
<image src="../../static/icon/mine_v.png"></image> <image src="../../static/icon/mine_v.png"></image>
尊贵的VIP会员 尊贵的VIP会员
<font style="font-size: 14rpx;margin-left: 20rpx;">{{userMes.vipValidtime}}到期</font> <font style="font-size: 14rpx;margin-left: 20rpx;">{{userMes.vipValidtime}}到期</font>
</text> </text>
<b class="kt_btn" @click="onPageJump('./opeVip')">立即续费</b> <b class="kt_btn" @click="onPageJump('./opeVip')">立即续费</b>
</view> </view> -->
<view class="chong_zhi"> <view class="chong_zhi">
<view class="zhanghu" @click="onPageJump('../user/persCount')"> <view class="zhanghu" @click="onPageJump('../user/persCount')">

View File

@@ -12,7 +12,7 @@
<text v-for="item in historyList" @click="serkeyWord(item)">{{item}}</text> <text v-for="item in historyList" @click="serkeyWord(item)">{{item}}</text>
</view> </view>
</view> </view>
<view class="sear_class" v-if="this.show==1"> <!-- <view class="sear_class" v-if="this.show==1">
<view class="sc_xuan"> <view class="sc_xuan">
<view class="sc_con" v-for="(item,index) in classFen" @click="FenBook(item)" <view class="sc_con" v-for="(item,index) in classFen" @click="FenBook(item)"
:class="bookScreen.type == item.id ? 'sc_con sc_con_style' : 'sc_con'">{{item.sort}}</view> :class="bookScreen.type == item.id ? 'sc_con sc_con_style' : 'sc_con'">{{item.sort}}</view>
@@ -21,14 +21,14 @@
<view class="sc_con" v-for="(item,index) in classMian" @click="MianBook(item)" <view class="sc_con" v-for="(item,index) in classMian" @click="MianBook(item)"
:class="bookScreen.is_charge == item.id ? 'sc_con sc_con_style' : 'sc_con'">{{item.sort}}</view> :class="bookScreen.is_charge == item.id ? 'sc_con sc_con_style' : 'sc_con'">{{item.sort}}</view>
</view> </view>
</view> </view> -->
<view class="sear_list" v-if="this.show==1"> <view class="sear_list" v-if="this.show==1">
<view class="bl_tioa" v-for="(item,index) in bookList" @click="onBookJump(item)"> <view class="bl_tioa" v-for="(item,index) in bookList" @click="onBookJump(item)">
<image :src="item.images"></image> <image :src="item.productImages"></image>
<view> <view>
<text class="bok_name">{{item.name}}</text> <text class="bok_name">{{item.productName}}</text>
</view> </view>
<view> <!-- <view>
<text>作者<text style="color: #333;">{{item.authorName}}</text></text> <text>作者<text style="color: #333;">{{item.authorName}}</text></text>
</view> </view>
<view> <view>
@@ -36,7 +36,7 @@
</view> </view>
<view> <view>
<text style="line-height: 20rpx;">{{item.title}}</text> <text style="line-height: 20rpx;">{{item.title}}</text>
</view> </view> -->
</view> </view>
<view style="height: 1px;"></view> <view style="height: 1px;"></view>
<view> <view>
@@ -121,7 +121,8 @@
this.bookScreen.page = this.bookScreen.page + 1 this.bookScreen.page = this.bookScreen.page + 1
setTimeout(() => { setTimeout(() => {
this.$http this.$http
.post('book/book/list', this.bookScreen) // .post('book/book/list', this.bookScreen)
.post('book/shopproduct/selectList?limit=8&page=1&key='+this.bookScreen.bookName)
.then(res => { .then(res => {
this.totalPage = res.page.totalPage this.totalPage = res.page.totalPage
for (let i in res.page.list) { for (let i in res.page.list) {
@@ -162,8 +163,10 @@
// 获取列表数据 // 获取列表数据
getData() { getData() {
this.$http this.$http
.post('book/book/list', this.bookScreen) // .post('book/book/list', this.bookScreen)
.post('book/shopproduct/selectList?limit=8&page=1&key='+ this.bookScreen.bookName)
.then(res => { .then(res => {
console.log(res)
this.bookList = res.page.list this.bookList = res.page.list
this.totalPage = res.page.totalPage this.totalPage = res.page.totalPage
this.status = 3 this.status = 3
@@ -223,9 +226,12 @@
// 电子书内容跳转 // 电子书内容跳转
onBookJump(e) { onBookJump(e) {
console.log(e,'e')
uni.navigateTo({ uni.navigateTo({
url: '../eBook/bookContent?Id=' + e.id // url: '../eBook/bookContent?Id=' + e.id
url: '../bookShop/commodityDetail?type=2&id=' + e.productId
}); });
}, },
}, },
}; };
@@ -280,20 +286,22 @@
} }
.sear_list { .sear_list {
margin: 50rpx 30rpx 0 30rpx; margin: 50rpx 30rpx 0 30rpx; display: flex; flex-wrap: wrap; justify-content: space-between;
.bl_tioa { .bl_tioa {
box-shadow: 0 0px 10px 1px #d3d1d133; width: 30%;
background-color: #fff; box-shadow: 0 0px 10px 1px #d3d1d133; padding-bottom: 10rpx;
position: relative; background-color: #fff; margin-bottom: 20rpx;
padding: 0 25upx 10upx 220upx; // position: relative;
margin: 0 0 60rpx 0; // padding: 0 25upx 10upx 220upx;
// margin: 0 0 60rpx 0;
text-align: center;
border-radius: 15rpx; border-radius: 15rpx;
min-height: 250rpx; min-height: 250rpx;
view { view {
display: block;
text { text { display: block;
color: #9b9b9b; color: #9b9b9b;
font-size: 24rpx; font-size: 24rpx;
line-height: 36rpx; line-height: 36rpx;
@@ -306,12 +314,10 @@
} }
} }
image { image { display: inline-block;
position: absolute; padding-top:20rpx;
left: 30upx;
top: -20upx;
width: 160upx; width: 160upx;
height: 240upx; height: 220upx;
} }
} }

BIN
static/emotion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
static/icon/bgleft1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
static/icon/bgleft2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
static/icon/bgright1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
static/icon/bgright2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
static/icon/bgtushu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
static/icon/home1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
static/icon/home2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
static/icon/home3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
static/icon/home4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
static/icon/home_bg1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
static/icon/home_icon_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
static/icon/searchBg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/icon/tu1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/icon/tu2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
static/icon/tu3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/icon/wufeng.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
static/icon/zuotouming.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/tab/tab1-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
static/tab/tab1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
static/tab/tab2-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
static/tab/tab2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/tab/tab3-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/tab/tab3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
static/tab/tab4-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
static/tab/tab4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,26 @@
## 1.4.102023-04-10
- 修复 某些情况 monthSwitch 未触发的Bug
## 1.4.92023-02-02
- 修复 某些情况切换月份错误的Bug
## 1.4.82023-01-30
- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
## 1.4.72022-09-16
- 优化 支持使用 uni-scss 控制主题色
## 1.4.62022-09-08
- 修复 表头年月切换导致改变当前日期为选择月1号且未触发change事件的Bug
## 1.4.52022-02-25
- 修复 条件编译 nvue 不支持的 css 样式的Bug
## 1.4.42022-02-25
- 修复 条件编译 nvue 不支持的 css 样式的Bug
## 1.4.32021-09-22
- 修复 startDate、 endDate 属性失效的Bug
## 1.4.22021-08-24
- 新增 支持国际化
## 1.4.12021-08-05
- 修复 弹出层被 tabbar 遮盖的Bug
## 1.4.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.3.162021-05-12
- 新增 组件示例地址
## 1.3.152021-02-04
- 调整为uni_modules目录规范

View File

@@ -0,0 +1,546 @@
/**
* @1900-2100区间内的公历、农历互转
* @charset UTF-8
* @github https://github.com/jjonline/calendar.js
* @Author Jea杨(JJonline@JJonline.Cn)
* @Time 2014-7-21
* @Time 2016-8-13 Fixed 2033hex、Attribution Annals
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
* @Version 1.0.3
* @公历转农历calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
* @农历转公历calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
*/
/* eslint-disable */
var calendar = {
/**
* 农历1900-2100的润大小信息表
* @Array Of Property
* @return Hex
*/
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
/** Add By JJonline@JJonline.Cn**/
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
0x0d520], // 2100
/**
* 公历每个月份的天数普通表
* @Array Of Property
* @return Number
*/
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
/**
* 天干地支之天干速查表
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
* @return Cn string
*/
Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
/**
* 天干地支之地支速查表
* @Array Of Property
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
* @return Cn string
*/
Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
/**
* 天干地支之地支速查表<=>生肖
* @Array Of Property
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @return Cn string
*/
Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
/**
* 24节气速查表
* @Array Of Property
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
* @return Cn string
*/
solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
/**
* 1900-2100各年的24节气日期速查表
* @Array Of Property
* @return 0x string For splice
*/
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
/**
* 数字转中文速查表
* @Array Of Property
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
* @return Cn string
*/
nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
/**
* 日期转农历称呼速查表
* @Array Of Property
* @trans ['初','十','廿','卅']
* @return Cn string
*/
nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
/**
* 月份转农历称呼速查表
* @Array Of Property
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
* @return Cn string
*/
nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
/**
* 返回农历y年一整年的总天数
* @param lunar Year
* @return Number
* @eg:var count = calendar.lYearDays(1987) ;//count=387
*/
lYearDays: function (y) {
var i; var sum = 348
for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
return (sum + this.leapDays(y))
},
/**
* 返回农历y年闰月是哪个月若y年没有闰月 则返回0
* @param lunar Year
* @return Number (0-12)
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
*/
leapMonth: function (y) { // 闰字编码 \u95f0
return (this.lunarInfo[y - 1900] & 0xf)
},
/**
* 返回农历y年闰月的天数 若该年没有闰月则返回0
* @param lunar Year
* @return Number (0、29、30)
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
*/
leapDays: function (y) {
if (this.leapMonth(y)) {
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
}
return (0)
},
/**
* 返回农历y年m月非闰月的总天数计算m为闰月时的天数请使用leapDays方法
* @param lunar Year
* @return Number (-1、29、30)
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
*/
monthDays: function (y, m) {
if (m > 12 || m < 1) { return -1 }// 月份参数从1至12参数错误返回-1
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
},
/**
* 返回公历(!)y年m月的天数
* @param solar Year
* @return Number (-1、28、29、30、31)
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
*/
solarDays: function (y, m) {
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
var ms = m - 1
if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
} else {
return (this.solarMonth[ms])
}
},
/**
* 农历年份转换为干支纪年
* @param lYear 农历年的年份数
* @return Cn string
*/
toGanZhiYear: function (lYear) {
var ganKey = (lYear - 3) % 10
var zhiKey = (lYear - 3) % 12
if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
},
/**
* 公历月、日判断所属星座
* @param cMonth [description]
* @param cDay [description]
* @return Cn string
*/
toAstro: function (cMonth, cDay) {
var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
},
/**
* 传入offset偏移量返回干支
* @param offset 相对甲子的偏移量
* @return Cn string
*/
toGanZhi: function (offset) {
return this.Gan[offset % 10] + this.Zhi[offset % 12]
},
/**
* 传入公历(!)y年获得该年第n个节气的公历日期
* @param y公历年(1900-2100)n二十四节气中的第几个节气(1~24)从n=1(小寒)算起
* @return day Number
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
*/
getTerm: function (y, n) {
if (y < 1900 || y > 2100) { return -1 }
if (n < 1 || n > 24) { return -1 }
var _table = this.sTermInfo[y - 1900]
var _info = [
parseInt('0x' + _table.substr(0, 5)).toString(),
parseInt('0x' + _table.substr(5, 5)).toString(),
parseInt('0x' + _table.substr(10, 5)).toString(),
parseInt('0x' + _table.substr(15, 5)).toString(),
parseInt('0x' + _table.substr(20, 5)).toString(),
parseInt('0x' + _table.substr(25, 5)).toString()
]
var _calday = [
_info[0].substr(0, 1),
_info[0].substr(1, 2),
_info[0].substr(3, 1),
_info[0].substr(4, 2),
_info[1].substr(0, 1),
_info[1].substr(1, 2),
_info[1].substr(3, 1),
_info[1].substr(4, 2),
_info[2].substr(0, 1),
_info[2].substr(1, 2),
_info[2].substr(3, 1),
_info[2].substr(4, 2),
_info[3].substr(0, 1),
_info[3].substr(1, 2),
_info[3].substr(3, 1),
_info[3].substr(4, 2),
_info[4].substr(0, 1),
_info[4].substr(1, 2),
_info[4].substr(3, 1),
_info[4].substr(4, 2),
_info[5].substr(0, 1),
_info[5].substr(1, 2),
_info[5].substr(3, 1),
_info[5].substr(4, 2)
]
return parseInt(_calday[n - 1])
},
/**
* 传入农历数字月份返回汉语通俗表示法
* @param lunar month
* @return Cn string
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
*/
toChinaMonth: function (m) { // 月 => \u6708
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
var s = this.nStr3[m - 1]
s += '\u6708'// 加上月字
return s
},
/**
* 传入农历日期数字返回汉字表示法
* @param lunar day
* @return Cn string
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
*/
toChinaDay: function (d) { // 日 => \u65e5
var s
switch (d) {
case 10:
s = '\u521d\u5341'; break
case 20:
s = '\u4e8c\u5341'; break
break
case 30:
s = '\u4e09\u5341'; break
break
default :
s = this.nStr2[Math.floor(d / 10)]
s += this.nStr1[d % 10]
}
return (s)
},
/**
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
* @param y year
* @return Cn string
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
*/
getAnimal: function (y) {
return this.Animals[(y - 4) % 12]
},
/**
* 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
* @param y solar year
* @param m solar month
* @param d solar day
* @return JSON object
* @eg:console.log(calendar.solar2lunar(1987,11,01));
*/
solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
// 年份限定、上限
if (y < 1900 || y > 2100) {
return -1// undefined转换为数字变为NaN
}
// 公历传参最下限
if (y == 1900 && m == 1 && d < 31) {
return -1
}
// 未传参 获得当天
if (!y) {
var objDate = new Date()
} else {
var objDate = new Date(y, parseInt(m) - 1, d)
}
var i; var leap = 0; var temp = 0
// 修正ymd参数
var y = objDate.getFullYear()
var m = objDate.getMonth() + 1
var d = objDate.getDate()
var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
for (i = 1900; i < 2101 && offset > 0; i++) {
temp = this.lYearDays(i)
offset -= temp
}
if (offset < 0) {
offset += temp; i--
}
// 是否今天
var isTodayObj = new Date()
var isToday = false
if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
isToday = true
}
// 星期几
var nWeek = objDate.getDay()
var cWeek = this.nStr1[nWeek]
// 数字表示周几顺应天朝周一开始的惯例
if (nWeek == 0) {
nWeek = 7
}
// 农历年
var year = i
var leap = this.leapMonth(i) // 闰哪个月
var isLeap = false
// 效验闰月
for (i = 1; i < 13 && offset > 0; i++) {
// 闰月
if (leap > 0 && i == (leap + 1) && isLeap == false) {
--i
isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
} else {
temp = this.monthDays(year, i)// 计算农历普通月天数
}
// 解除闰月
if (isLeap == true && i == (leap + 1)) { isLeap = false }
offset -= temp
}
// 闰月导致数组下标重叠取反
if (offset == 0 && leap > 0 && i == leap + 1) {
if (isLeap) {
isLeap = false
} else {
isLeap = true; --i
}
}
if (offset < 0) {
offset += temp; --i
}
// 农历月
var month = i
// 农历日
var day = offset + 1
// 天干地支处理
var sm = m - 1
var gzY = this.toGanZhiYear(year)
// 当月的两个节气
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
// 依据12节气修正干支月
var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
if (d >= firstNode) {
gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
}
// 传入的日期的节气与否
var isTerm = false
var Term = null
if (firstNode == d) {
isTerm = true
Term = this.solarTerm[m * 2 - 2]
}
if (secondNode == d) {
isTerm = true
Term = this.solarTerm[m * 2 - 1]
}
// 日柱 当月一日与 1900/1/1 相差天数
var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
var gzD = this.toGanZhi(dayCyclical + d - 1)
// 该日期所属的星座
var astro = this.toAstro(m, d)
return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
},
/**
* 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
* @param y lunar year
* @param m lunar month
* @param d lunar day
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
* @return JSON object
* @eg:console.log(calendar.lunar2solar(1987,9,10));
*/
lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
var isLeapMonth = !!isLeapMonth
var leapOffset = 0
var leapMonth = this.leapMonth(y)
var leapDay = this.leapDays(y)
if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
var day = this.monthDays(y, m)
var _day = day
// bugFix 2016-9-25
// if month is leap, _day use leapDays method
if (isLeapMonth) {
_day = this.leapDays(y, m)
}
if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
// 计算农历的时间差
var offset = 0
for (var i = 1900; i < y; i++) {
offset += this.lYearDays(i)
}
var leap = 0; var isAdd = false
for (var i = 1; i < m; i++) {
leap = this.leapMonth(y)
if (!isAdd) { // 处理闰月
if (leap <= i && leap > 0) {
offset += this.leapDays(y); isAdd = true
}
}
offset += this.monthDays(y, i)
}
// 转换闰月农历 需补充该年闰月的前一个月的时差
if (isLeapMonth) { offset += day }
// 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
var calObj = new Date((offset + d - 31) * 86400000 + stmap)
var cY = calObj.getUTCFullYear()
var cM = calObj.getUTCMonth() + 1
var cD = calObj.getUTCDate()
return this.solar2lunar(cY, cM, cD)
}
}
export default calendar

View File

@@ -0,0 +1,12 @@
{
"uni-calender.ok": "ok",
"uni-calender.cancel": "cancel",
"uni-calender.today": "today",
"uni-calender.MON": "MON",
"uni-calender.TUE": "TUE",
"uni-calender.WED": "WED",
"uni-calender.THU": "THU",
"uni-calender.FRI": "FRI",
"uni-calender.SAT": "SAT",
"uni-calender.SUN": "SUN"
}

View File

@@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@@ -0,0 +1,12 @@
{
"uni-calender.ok": "确定",
"uni-calender.cancel": "取消",
"uni-calender.today": "今日",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六"
}

View File

@@ -0,0 +1,12 @@
{
"uni-calender.ok": "確定",
"uni-calender.cancel": "取消",
"uni-calender.today": "今日",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六"
}

View File

@@ -0,0 +1,187 @@
<template>
<view class="uni-calendar-item__weeks-box" :class="{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
}"
@click="choiceDate(weeks)">
<view class="uni-calendar-item__weeks-box-item">
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text" :class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.date}}</text>
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
}">{{todayText}}</text>
<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--extra':weeks.extraInfo.info,
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.extraInfo.info}}</text>
</view>
</view>
</template>
<script>
import { initVueI18n } from '@dcloudio/uni-i18n'
import i18nMessages from './i18n/index.js'
const { t } = initVueI18n(i18nMessages)
export default {
emits:['change'],
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
}
},
computed: {
todayText() {
return t("uni-calender.today")
},
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
}
}
}
</script>
<style lang="scss" scoped>
$uni-font-size-base:14px;
$uni-text-color:#333;
$uni-font-size-sm:12px;
$uni-color-error: #e43d33;
$uni-opacity-disabled: 0.3;
$uni-text-color-disable:#c0c0c0;
$uni-primary: #2979ff !default;
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
}
.uni-calendar-item__weeks-box-text {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar-item__weeks-lunar-text {
font-size: $uni-font-size-sm;
color: $uni-text-color;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: $uni-color-error;
}
.uni-calendar-item--disable {
background-color: rgba(249, 249, 249, $uni-opacity-disabled);
color: $uni-text-color-disable;
}
.uni-calendar-item--isDay-text {
color: $uni-primary;
}
.uni-calendar-item--isDay {
background-color: $uni-primary;
opacity: 0.8;
color: #fff;
}
.uni-calendar-item--extra {
color: $uni-color-error;
opacity: 0.8;
}
.uni-calendar-item--checked {
background-color: $uni-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--multiple {
background-color: $uni-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--before-checked {
background-color: #ff5a5f;
color: #fff;
}
.uni-calendar-item--after-checked {
background-color: #ff5a5f;
color: #fff;
}
</style>

View File

@@ -0,0 +1,566 @@
<template>
<view class="uni-calendar">
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view>
<view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
<view class="uni-calendar__header-btn-box" @click="close">
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
</view>
<view class="uni-calendar__header-btn-box" @click="confirm">
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
</view>
</view>
<view class="uni-calendar__header">
<view class="uni-calendar__header-btn-box" @click.stop="pre">
<view class="uni-calendar__header-btn uni-calendar--left"></view>
</view>
<picker mode="date" :value="date" fields="month" @change="bindDateChange">
<text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text>
</picker>
<view class="uni-calendar__header-btn-box" @click.stop="next">
<view class="uni-calendar__header-btn uni-calendar--right"></view>
</view>
<text class="uni-calendar__backtoday" @click="backToday">{{todayText}}</text>
</view>
<view class="uni-calendar__box">
<view v-if="showMonth" class="uni-calendar__box-bg">
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
</view>
<view class="uni-calendar__weeks">
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{monText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
</view>
</view>
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import Calendar from './util.js';
import CalendarItem from './uni-calendar-item.vue'
import { initVueI18n } from '@dcloudio/uni-i18n'
import i18nMessages from './i18n/index.js'
const { t } = initVueI18n(i18nMessages)
/**
* Calendar 日历
* @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
* @tutorial https://ext.dcloud.net.cn/plugin?id=56
* @property {String} date 自定义当前时间,默认为今天
* @property {Boolean} lunar 显示农历
* @property {String} startDate 日期选择范围-开始日期
* @property {String} endDate 日期选择范围-结束日期
* @property {Boolean} range 范围选择
* @property {Boolean} insert = [true|false] 插入模式,默认为false
* @value true 弹窗模式
* @value false 插入模式
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
* @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
* @property {Boolean} showMonth 是否选择月份为背景
* @event {Function} change 日期改变,`insert :ture` 时生效
* @event {Function} confirm 确认选择`insert :false` 时生效
* @event {Function} monthSwitch 切换月份时触发
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
*/
export default {
components: {
CalendarItem
},
emits:['close','confirm','change','monthSwitch'],
props: {
date: {
type: String,
default: ''
},
selected: {
type: Array,
default () {
return []
}
},
lunar: {
type: Boolean,
default: false
},
startDate: {
type: String,
default: ''
},
endDate: {
type: String,
default: ''
},
range: {
type: Boolean,
default: false
},
insert: {
type: Boolean,
default: true
},
showMonth: {
type: Boolean,
default: true
},
clearDate: {
type: Boolean,
default: true
}
},
data() {
return {
show: false,
weeks: [],
calendar: {},
nowDate: '',
aniMaskShow: false
}
},
computed:{
/**
* for i18n
*/
okText() {
return t("uni-calender.ok")
},
cancelText() {
return t("uni-calender.cancel")
},
todayText() {
return t("uni-calender.today")
},
monText() {
return t("uni-calender.MON")
},
TUEText() {
return t("uni-calender.TUE")
},
WEDText() {
return t("uni-calender.WED")
},
THUText() {
return t("uni-calender.THU")
},
FRIText() {
return t("uni-calender.FRI")
},
SATText() {
return t("uni-calender.SAT")
},
SUNText() {
return t("uni-calender.SUN")
},
},
watch: {
date(newVal) {
// this.cale.setDate(newVal)
this.init(newVal)
},
startDate(val){
this.cale.resetSatrtDate(val)
this.cale.setDate(this.nowDate.fullDate)
this.weeks = this.cale.weeks
},
endDate(val){
this.cale.resetEndDate(val)
this.cale.setDate(this.nowDate.fullDate)
this.weeks = this.cale.weeks
},
selected(newVal) {
this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
this.weeks = this.cale.weeks
}
},
created() {
this.cale = new Calendar({
selected: this.selected,
startDate: this.startDate,
endDate: this.endDate,
range: this.range,
})
this.init(this.date)
},
methods: {
// 取消穿透
clean() {},
bindDateChange(e) {
const value = e.detail.value + '-1'
this.setDate(value)
const { year,month } = this.cale.getDate(value)
this.$emit('monthSwitch', {
year,
month
})
},
/**
* 初始化日期显示
* @param {Object} date
*/
init(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.calendar = this.cale.getInfo(date)
},
/**
* 打开日历弹窗
*/
open() {
// 弹窗模式并且清理数据
if (this.clearDate && !this.insert) {
this.cale.cleanMultipleStatus()
// this.cale.setDate(this.date)
this.init(this.date)
}
this.show = true
this.$nextTick(() => {
setTimeout(() => {
this.aniMaskShow = true
}, 50)
})
},
/**
* 关闭日历弹窗
*/
close() {
this.aniMaskShow = false
this.$nextTick(() => {
setTimeout(() => {
this.show = false
this.$emit('close')
}, 300)
})
},
/**
* 确认按钮
*/
confirm() {
this.setEmit('confirm')
this.close()
},
/**
* 变化触发
*/
change() {
if (!this.insert) return
this.setEmit('change')
},
/**
* 选择月份触发
*/
monthSwitch() {
let {
year,
month
} = this.nowDate
this.$emit('monthSwitch', {
year,
month: Number(month)
})
},
/**
* 派发事件
* @param {Object} name
*/
setEmit(name) {
let {
year,
month,
date,
fullDate,
lunar,
extraInfo
} = this.calendar
this.$emit(name, {
range: this.cale.multipleStatus,
year,
month,
date,
fulldate: fullDate,
lunar,
extraInfo: extraInfo || {}
})
},
/**
* 选择天触发
* @param {Object} weeks
*/
choiceDate(weeks) {
if (weeks.disable) return
this.calendar = weeks
// 设置多选
this.cale.setMultiple(this.calendar.fullDate)
this.weeks = this.cale.weeks
this.change()
},
/**
* 回到今天
*/
backToday() {
const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}`
const date = this.cale.getDate(new Date())
const todayYearMonth = `${date.year}-${date.month}`
if(nowYearMonth !== todayYearMonth) {
this.monthSwitch()
}
this.init(date.fullDate)
this.change()
},
/**
* 上个月
*/
pre() {
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
this.setDate(preDate)
this.monthSwitch()
},
/**
* 下个月
*/
next() {
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
this.setDate(nextDate)
this.monthSwitch()
},
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.cale.getInfo(date)
}
}
}
</script>
<style lang="scss" scoped>
$uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
$uni-border-color: #EDEDED;
$uni-text-color: #333;
$uni-bg-color-hover:#f1f1f1;
$uni-font-size-base:14px;
$uni-text-color-placeholder: #808080;
$uni-color-subtitle: #555555;
$uni-text-color-grey:#999;
.uni-calendar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.uni-calendar__mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--mask-show {
opacity: 1
}
.uni-calendar--fixed {
position: fixed;
/* #ifdef APP-NVUE */
bottom: 0;
/* #endif */
left: 0;
right: 0;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460px);
/* #ifndef APP-NVUE */
bottom: calc(var(--window-bottom));
z-index: 99;
/* #endif */
}
.uni-calendar--ani-show {
transform: translateY(0);
}
.uni-calendar__content {
background-color: #fff;
}
.uni-calendar__header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
height: 50px;
border-bottom-color: $uni-border-color;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.uni-calendar--fixed-top {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--fixed-width {
width: 50px;
}
.uni-calendar__backtoday {
position: absolute;
right: 0;
top: 25rpx;
padding: 0 5px;
padding-left: 10px;
height: 25px;
line-height: 25px;
font-size: 12px;
border-top-left-radius: 25px;
border-bottom-left-radius: 25px;
color: $uni-text-color;
background-color: $uni-bg-color-hover;
}
.uni-calendar__header-text {
text-align: center;
width: 100px;
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar__header-btn-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
}
.uni-calendar__header-btn {
width: 10px;
height: 10px;
border-left-color: $uni-text-color-placeholder;
border-left-style: solid;
border-left-width: 2px;
border-top-color: $uni-color-subtitle;
border-top-style: solid;
border-top-width: 2px;
}
.uni-calendar--left {
transform: rotate(-45deg);
}
.uni-calendar--right {
transform: rotate(135deg);
}
.uni-calendar__weeks {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-calendar__weeks-item {
flex: 1;
}
.uni-calendar__weeks-day {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
height: 45px;
border-bottom-color: #F5F5F5;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.uni-calendar__weeks-day-text {
font-size: 14px;
}
.uni-calendar__box {
position: relative;
}
.uni-calendar__box-bg {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.uni-calendar__box-bg-text {
font-size: 200px;
font-weight: bold;
color: $uni-text-color-grey;
opacity: 0.1;
text-align: center;
/* #ifndef APP-NVUE */
line-height: 1;
/* #endif */
}
</style>

View File

@@ -0,0 +1,360 @@
import CALENDAR from './calendar.js'
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range
} = {}) {
// 当前日期
this.date = this.getDate(new Date()) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
this.startDate = startDate
// 范围结束
this.endDate = endDate
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
// this._getWeek(this.date.fullDate)
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.selectDate = this.getDate(date)
this._getWeek(this.selectDate.fullDate)
}
/**
* 清理多选状态
*/
cleanMultipleStatus() {
this.multipleStatus = {
before: '',
after: '',
data: []
}
}
/**
* 重置开始日期
*/
resetSatrtDate(startDate) {
// 范围开始
this.startDate = startDate
}
/**
* 重置结束日期
*/
resetEndDate(endDate) {
// 范围结束
this.endDate = endDate
}
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = 'day') {
if (!date) {
date = new Date()
}
if (typeof date !== 'object') {
date = date.replace(/-/g, '/')
}
const dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
break
case 'month':
if (dd.getDate() === 31 && AddDayCount>0) {
dd.setDate(dd.getDate() + AddDayCount)
} else {
const preMonth = dd.getMonth()
dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
const nextMonth = dd.getMonth()
// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
}
// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
}
}
break
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
break
}
const y = dd.getFullYear()
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号不足10补0
return {
fullDate: y + '-' + m + '-' + d,
year: y,
month: m,
date: d,
day: dd.getDay()
}
}
/**
* 获取上月剩余天数
*/
_getLastMonthDays(firstDay, full) {
let dateArr = []
for (let i = firstDay; i > 0; i--) {
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
dateArr.push({
date: beforeDate,
month: full.month - 1,
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
disable: true
})
}
return dateArr
}
/**
* 获取本月天数
*/
_currentMonthDys(dateData, full) {
let dateArr = []
let fullDate = this.date.fullDate
for (let i = 1; i <= dateData; i++) {
let nowDate = full.year + '-' + (full.month < 10 ?
full.month : full.month) + '-' + (i < 10 ?
'0' + i : i)
// 是否今天
let isDay = fullDate === nowDate
// 获取打点信息
let info = this.selected && this.selected.find((item) => {
if (this.dateEqual(nowDate, item.date)) {
return item
}
})
// 日期禁用
let disableBefore = true
let disableAfter = true
if (this.startDate) {
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
disableBefore = this.dateCompare(this.startDate, nowDate)
}
if (this.endDate) {
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
disableAfter = this.dateCompare(nowDate, this.endDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
if (this.range) {
if (multiples) {
multiplesStatus = multiples.findIndex((item) => {
return this.dateEqual(item, nowDate)
})
}
if (multiplesStatus !== -1) {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
month: full.month,
lunar: this.getlunar(full.year, full.month, i),
disable: !(disableBefore && disableAfter),
isDay
}
if (info) {
data.extraInfo = info
}
dateArr.push(data)
}
return dateArr
}
/**
* 获取下月天数
*/
_getNextMonthDays(surplus, full) {
let dateArr = []
for (let i = 1; i < surplus + 1; i++) {
dateArr.push({
date: i,
month: Number(full.month) + 1,
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
disable: true
})
}
return dateArr
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo(date) {
if (!date) {
date = new Date()
}
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
return dateInfo
}
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
// 计算截止时间
before = new Date(before.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
/**
* 获取日期范围内所有日期
* @param {Object} begin
* @param {Object} end
*/
geDateAll(begin, end) {
var arr = []
var ab = begin.split('-')
var ae = end.split('-')
var db = new Date()
db.setFullYear(ab[0], ab[1] - 1, ab[2])
var de = new Date()
de.setFullYear(ae[0], ae[1] - 1, ae[2])
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
for (var k = unixDb; k <= unixDe;) {
k = k + 24 * 60 * 60 * 1000
arr.push(this.getDate(new Date(parseInt(k))).fullDate)
}
return arr
}
/**
* 计算阴历日期显示
*/
getlunar(year, month, date) {
return CALENDAR.solar2lunar(year, month, date)
}
/**
* 设置打点
*/
setSelectInfo(data, value) {
this.selected = value
this._getWeek(data)
}
/**
* 获取多选状态
*/
setMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (before && after) {
this.multipleStatus.before = ''
this.multipleStatus.after = ''
this.multipleStatus.data = []
} else {
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
}
}
}
this._getWeek(fullDate)
}
/**
* 获取每周数据
* @param {Object} dateData
*/
_getWeek(dateData) {
const {
year,
month
} = this.getDate(dateData)
let firstDay = new Date(year, month - 1, 1).getDay()
let currentDay = new Date(year, month, 0).getDate()
let dates = {
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
nextMonthDays: [], // 下个月开始几天
weeks: []
}
let canlender = []
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
let weeks = {}
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
weeks[parseInt(i / 7)] = new Array(7)
}
weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
this.canlender = canlender
this.weeks = weeks
}
//静态方法
// static init(date) {
// if (!this.instance) {
// this.instance = new Calendar(date);
// }
// return this.instance;
// }
}
export default Calendar

View File

@@ -0,0 +1,85 @@
{
"id": "uni-calendar",
"displayName": "uni-calendar 日历",
"version": "1.4.10",
"description": "日历组件",
"keywords": [
"uni-ui",
"uniui",
"日历",
"",
"打卡",
"日历选择"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@@ -0,0 +1,103 @@
## Calendar 日历
> **组件名uni-calendar**
> 代码块: `uCalendar`
日历组件
> **注意事项**
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js)
> - 仅支持自定义组件模式
> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date()
> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意
> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动
### 安装方式
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
### 基本用法
在 ``template`` 中使用组件
```html
<view>
<uni-calendar
:insert="true"
:lunar="true"
:start-date="'2019-3-2'"
:end-date="'2019-5-20'"
@change="change"
/>
</view>
```
### 通过方法打开日历
需要设置 `insert` 为 `false`
```html
<view>
<uni-calendar
ref="calendar"
:insert="false"
@confirm="confirm"
/>
<button @click="open">打开日历</button>
</view>
```
```javascript
export default {
data() {
return {};
},
methods: {
open(){
this.$refs.calendar.open();
},
confirm(e) {
console.log(e);
}
}
};
```
## API
### Calendar Props
| 属性名 | 类型 | 默认值| 说明 |
| - | - | - | - |
| date | String |- | 自定义当前时间,默认为今天 |
| lunar | Boolean | false | 显示农历 |
| startDate | String |- | 日期选择范围-开始日期 |
| endDate | String |- | 日期选择范围-结束日期 |
| range | Boolean | false | 范围选择 |
| insert | Boolean | false | 插入模式,可选值ture插入模式false弹窗模式默认为插入模式 |
|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 |
| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
|showMonth | Boolean | true | 是否显示月份为背景 |
### Calendar Events
| 事件名 | 说明 |返回值|
| - | - | - |
| open | 弹出日历组件,`insert :false` 时生效|- |
## 组件示例
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)

View File

@@ -62,21 +62,29 @@ var music = {
console.log('暂停背景音乐'); console.log('暂停背景音乐');
this.saveTimes() this.saveTimes()
clearInterval(bgm.interval) clearInterval(bgm.interval)
bgm.interval = null
bgm.playing = false
store.commit('setUserInfo',{'playFlag': false}) store.commit('setUserInfo',{'playFlag': false})
}) })
bgm.onPlay(() => { bgm.onPlay(() => {
store.commit('setUserInfo',{'playFlag': true}) store.commit('setUserInfo',{'playFlag': true})
console.log('开始播放音乐#######'); bgm.playing = true
console.log('开始播放音乐#######');
store.commit('setUserInfo',{'playingInfo': bgm.musicList[bgm.playIndex]})
console.log(store.state.userInfo.playingInfo,'chapterName2222')
uni.hideLoading() uni.hideLoading()
bgm.interval = setInterval(()=>{ bgm.interval = setInterval(()=>{
console.log('存一次') console.log('存一次')
this.saveIndex() // this.saveIndex()
store.commit('setUserInfo',{'playTimes': bgm.currentTime}) // 本地存储
this.saveRate(bgm.musicList[bgm.playIndex]) // 线上存储
},180000) },180000)
}) })
bgm.onError((res) => { bgm.onError((res) => {
console.log(res) console.log(res)
bgm.playing = false
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
showCancel:false, showCancel:false,
@@ -103,46 +111,57 @@ var music = {
}) })
bgm.onCanplay(() => { bgm.onCanplay(() => {
// 可以播放时 // 可以播放时
// console.log('可以播放时') console.log('可以播放时')
uni.hideLoading() uni.hideLoading()
// this.saveIndex() this.saveIndex()
console.log('历史播放进度,秒数', bgm.htimes) this.saveRate(bgm.musicList[bgm.playIndex])
// console.log('历史播放进度,秒数', bgm.htimes)
bgm.seek(bgm.htimes) bgm.seek(bgm.htimes)
bgm.htimes = 0 // 重置播放秒数 // console.log(bgm,'bgm')
// store.commit('setUserInfo',{'duration':bgm.duration})
// store.commit('setUserInfo',{'playTitle': bgm.title})
// store.commit('setUserInfo',{'fengImg': bgm.coverImgUrl})
// store.commit('setUserInfo',{'playFlag': true})
// store.commit('setUserInfo',{'playingInfo': bgm.musicList[bgm.playIndex]})
console.log(store.state.userInfo.playingInfo,'chapterName2222',bgm.playIndex)
}) })
bgm.onEnded(() => { bgm.onEnded(() => {
bgm.htimes = 0 // 重置播放秒数
bgm.playing = false
console.log('播放完毕了',bgm.playing) console.log('播放完毕了',bgm.playing)
store.commit('setUserInfo',{'playFlag': false}) store.commit('setUserInfo',{'playFlag': false})
this.setPlayIndex('next') // 下一首 this.setPlayIndex('next') // 下一首
}) })
}, },
// 添加播放列表 // 添加播放列表
setList(list,op,playindex){ setList(list,op,playindex,time){
// console.log(time,'time',playindex,'playindex')
bgm.musicList = list bgm.musicList = list
bgm.oldIndex = bgm.playIndex // 暂存上一个播放得index bgm.oldIndex = bgm.playIndex // 暂存上一个播放得index
console.log('地址异常报错前index:',bgm.oldIndex) // console.log('地址异常报错前index:',bgm.oldIndex)
playindex ? bgm.playIndex = playindex : bgm.playIndex = 0 // playindex ? bgm.playIndex = playindex : bgm.playIndex = 0
store.commit('setUserInfo',{'playingInfo': {}})
// console.log(bgm.playIndex,'playindex') if(playindex){
store.commit('setUserInfo',{'playingInfo': {}}) bgm.playIndex = playindex
this.getListenRate(bgm.musicList[0], op) console.log(playindex,'传值了')
// if(op == 'autoPlay'){ if(time){ // 如果传了历史播放秒数
// store.commit('setUserInfo',{'playTimes': 0}) bgm.htimes = time
// if(bgm._options.src == ''){ }else{
// // this.getChartUrl() // console.log('重置播放秒数')
// this.playBgm({mute:false}) bgm.htimes = 0
// console.log('playBgm') }
// }else{ }else{
// this.getChartUrl() // 获取对应的播放路径 console.log('---------')
// // console.log('getChartUrl') bgm.htimes = 0
// } bgm.playIndex = 0
// } }
if(op == 'autoPlay'){
store.commit('setUserInfo',{'playTimes': 0})
if(bgm._options.src == ''){
// this.getChartUrl()
// console.log(bgm,'+++++++++++')
this.playBgm({mute:false})
}else{
console.log(bgm, '----')
this.getChartUrl() // 获取对应的播放路径
}
}
}, },
// 获取线上听书进度 // 获取线上听书进度
getListenRate(val,op){ getListenRate(val,op){
@@ -169,8 +188,7 @@ var music = {
} }
}) })
store.commit('setUserInfo',{'playingInfo':bgm.musicList[bgm.playIndex] }) store.commit('setUserInfo',{'playingInfo':bgm.musicList[bgm.playIndex] })
console.log('线的播放index是',bgm.playIndex) // console.log('线的播放index是', store.state.userInfo.playingInfo)
console.log('线上的播放index是', store.state.userInfo.playingInfo)
}else{ }else{
// 没有听书进度 // 没有听书进度
} }
@@ -205,6 +223,9 @@ var music = {
// bgm.stop() // bgm.stop()
// 有听权限时 // 有听权限时
if(res.bookCatalogue[0].url){ // 空值url:null if(res.bookCatalogue[0].url){ // 空值url:null
// 先清除定时器
clearInterval(bgm.interval)
bgm.interval = null
bgm.src = res.bookCatalogue[0].url bgm.src = res.bookCatalogue[0].url
// bgm.title = res.bookCatalogue[0].name // bgm.title = res.bookCatalogue[0].name
// bgm.coverImgUrl = res.image // bgm.coverImgUrl = res.image
@@ -240,12 +261,12 @@ var music = {
bgm.playIndex = bgm.oldIndex bgm.playIndex = bgm.oldIndex
// bgm.stop() // bgm.stop()
// store.commit('setUserInfo',{'playFlag': false}) // store.commit('setUserInfo',{'playFlag': false})
if(e.errMsg.indexOf('未购买书籍') != -1){
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
cancelText: '暂不购买', cancelText: '暂不购买',
confirmText:'立即购买', confirmText:'立即购买',
content: '抱歉!当前章节不支持试听,购买后可收听', content: '抱歉!当前书籍未购买!',
success: function (res) { success: function (res) {
if (res.confirm) { if (res.confirm) {
console.log('用户点击确定'); console.log('用户点击确定');
@@ -255,17 +276,8 @@ var music = {
} }
} }
}); });
}
// uni.showModal({
// title: '提示',
// confirmText:'知道了',
// content: '当前书籍音频功能未开通,请联系管理员',
// success: function (res) {
// if (res.confirm) {
// console.log('用户点击确定');
// }
// }
// });
}) })
}, },
@@ -274,12 +286,17 @@ var music = {
console.log(bgm.playIndex,'存储得index') console.log(bgm.playIndex,'存储得index')
store.commit('setUserInfo',{'playIndex': bgm.playIndex}) store.commit('setUserInfo',{'playIndex': bgm.playIndex})
store.commit('setUserInfo',{'duration':bgm.duration}) store.commit('setUserInfo',{'duration':bgm.duration})
store.commit('setUserInfo',{'playTitle': bgm.title}) store.commit('setUserInfo',{'playTitle': bgm.musicList[bgm.playIndex].chapterName})
store.commit('setUserInfo',{'fengImg': bgm.coverImgUrl}) store.commit('setUserInfo',{'fengImg': bgm.musicList[bgm.playIndex].images})
store.commit('setUserInfo',{'playFlag': true}) store.commit('setUserInfo',{'playFlag': true})
store.commit('setUserInfo',{'playingInfo': bgm.musicList[bgm.playIndex]}) store.commit('setUserInfo',{'playingInfo': bgm.musicList[bgm.playIndex]})
store.commit('setUserInfo',{'playTimes': bgm.currentTime}) uni.setStorage({
this.saveRate(bgm.musicList[bgm.playIndex]) key: 'playingInfo',
data: bgm.musicList[bgm.playIndex],
success: function () {
console.log('success');
}
});
}, },
// 存储播放(本地) // 存储播放(本地)
saveTimes(){ saveTimes(){
@@ -292,10 +309,8 @@ var music = {
'userId': store.state.userInfo.id, 'userId': store.state.userInfo.id,
'bookId': val.bookid, 'bookId': val.bookid,
'chapterId': val.chapterId, 'chapterId': val.chapterId,
'chapterName': val.chapterName, 'chapterName': val.chapterName,
//'precent': bgm.currentTime 'precent': Math.ceil(bgm.currentTime),
'precent': Math.ceil(bgm.currentTime),
//'contentId'
'loadAnimate':'none', // 请求加载动画 'loadAnimate':'none', // 请求加载动画
}) })
.then(res => { .then(res => {
@@ -346,15 +361,11 @@ var music = {
getCoverImg(){ getCoverImg(){
// console.log(bgm.coverImgUrl,'bgm.coverImgUrl') // console.log(bgm.coverImgUrl,'bgm.coverImgUrl')
return bgm.coverImgUrl return bgm.coverImgUrl
}, },
// 获取播放列表
// getLibList(){
// return bgm.musicList
// },
// 播放单曲 // 播放单曲
setOneMusic(item){ setOneMusic(item){
console.log(item,'item') console.log(item,'item')
// 显示播放组件 // 显示播放组件
store.commit('setUserInfo',{'playVisible': true}) store.commit('setUserInfo',{'playVisible': true})
uni.setStorage({ uni.setStorage({