这是一个类播客类的小程序,功能包括内容推荐、音频播放、内容评论、收藏,主播详情、节目详情等内容。
功能上主要是以下几项:
精选,内容精选页(首页),Slide 滑动切换效果,类微信读书首页
柚道,内容为卡片流式列表,包含的内容为柚道类别下的:读书、读文内容,音频内容可直接点播放
柚答,育儿问题音频解答内容
教师(主播)详情页
柚道内容详情页,音频列表、评论列表,音频列表支持连续播放
柚道内容评论页
柚道内容收藏
交互上需要播放器与导航整合,可滑动切换,播放器默认停留的内容为精选页内容第一条
一期的需求,大致以上几条,还有我的里面会有各种内容收藏的详情页
code
<template>
<div class="index">
<img src="/static/images/banner.svg" class="banner"/>
<button open-type="getUserInfo"
@getuserinfo="bindGetUserInfo"
class="c-btn c-btn--primary c-btn--small" v-if="!isAuth">
授权登录
</button>
<img src="/static/images/footer.png" class="background"/>
</div>
</template>
<script>
import { wxLogin, setStorage, jumpTo, showLoading, hideLoading, modal, toast } from "../utils/wechatUtils";
import auth from "@/api/auth";
import userApi from '@/api/users'
export default {
data () {
return {
isAuth: true
}
},
methods: {
async bindGetUserInfo (e) {
showLoading()
this.isAuth = await auth.user({block: false, redirect: true}, e.mp.detail)
if (this.isAuth) {
hideLoading();
wx.switchTab({
url: '/pages/featured'
})
}
}
},
async mounted () {
const me = await userApi.me()
if (me) {
hideLoading();
wx.switchTab({
url: '/pages/featured'
})
} else {
this.isAuth = false
}
},
};
</script>
<style lang="scss">
$problemFontColor: #33270c;
.banner {
position: absolute;
top: 300rpx;
width: 750rpx;
height: 266rpx;
}
.background {
width: 464rpx;
height: 269rpx;
justify-content: center;
align-items: center;
text-align: center;
position: absolute;
bottom: 0;
z-index: 1;
}
.index {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
button:after {
border: none;
}
}
</style>
code
<style lang="scss">
Page, body {
background: #F5F5F7;
}
.o-page {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
</style>
<template>
<div class="o-page">
<slide :list="featured.list" :slideLength="slideLength" v-if="slideLength > 0 && featured.list"/>
<div class="u-flex u-justify-center u-align-items-center u-height-100" v-else>
<button class="c-btn c-btn--loading c-btn--flat c-btn--large " style="background: transparent;"></button>
</div>
<play-fab/>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import Slide from "@/components/slide";
import SlideItem from "@/components/slide/item";
import PlayFab from "@/components/play-fab";
import auth from "@/api/auth";
export default {
components: {
Slide,
SlideItem,
PlayFab
},
data () {
return {
// initialSlide: 0
};
},
computed: {
...mapState([
"featured"
]),
slideLength () {
if (this.featured.list) {
return this.featured.list.length;
}
// if (Object.is(this.featured, "list")) {
// if (Object.is(this.featured.list, "length")) {
// return this.featured.list.length;
// }
// }
return 0;
}
},
mounted () {
this.load();
// await auth.user()
},
// onLoad () {
// this.load();
// this.load()
// },
methods: {
...mapActions([
"getFeatured"
]),
async load () {
await auth.login();
await this.getFeatured();
}
}
};
</script>
code
<style lang="scss">
Page, body {
background: #F5F5F7;
font-size: 15px;
color: #2d3848;
line-height: 26px;
letter-spacing: 1.25px;
width: 100%;
height: 100%;
}
.o-page {
display: flex;
flex-direction: column;
}
.c-page__cover {
z-index: 1;
height: 200px;
position: relative;
display: flex;
flex-direction: column;
}
.c-page__body {
display: flex;
}
.c-section__title {
font-size: 16px;
}
.c-love-special {
background: #F5F5F7;
}
.c-special__cover {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
}
.c-special__author {
background: #fff;
display: flex;
flex-direction: row;
align-items: center;
/*padding: 20px;*/
padding-top: 20px;
.c-avatar {
width: 56px;
height: 56px;
}
&-info {
font-size: 16px;
padding-left: 10px;
display: flex;
flex-direction: column;
align-items: start;
line-height: 24px;
&__highlights {
font-size: 14px;
font-weight: 300;
}
}
}
.c-author__info {
display: flex;
flex-direction: column;
align-items: start;
}
.c-special__detail {
padding: 20px;
}
.replies {
&__header {
}
/*display: flex;*/
/*flex-direction: column;*/
&__list {
}
&__item {
padding: 20px;
display: flex;
flex-direction: row;
align-items: flex-start;
&-user {
display: flex;
height: auto;
&--avatar {
width: 36px;
height: 36px;
background-position: center center;
border-radius: 50px;
border: 2px solid #efefef;
}
}
&-info {
flex: 1;
margin-left: 15px;
&__nicename {
font-weight: 300;
display: inline-flex;
}
&--date {
float: right;
color: #D1D1D1;
font-weight: 300;
font-size: 12px;
}
&__content {
/*color: #7f8fa4;*/
color: #2d3848;
}
}
}
}
.c-placeholder {
transition: opacity 0.3s;
color: #fff;
opacity: 0.65;
}
.c-love-card--isHover {
}
.c-recalls--scroll {
display: flex;
white-space: nowrap;
width: rpx(780);
}
.c-recall-card {
/*box-sizing:border-box;*/
/*display: flex;*/
/*flex: 1;*/
/*height: rpx(360);*/
/*background: #fff;*/
/*box-shadow: 0 0 1px 1px rgba(0,0,0,0.05), 0 2px 2px 0 rgba(0,0,0,0.10);*/
/*border-radius: rpx(8);*/
/*padding: rpx(28) rpx(20) rpx(14);*/
/*position: relative;*/
/*align-items: center;*/
/*flex-direction: column;*/
/*position: relative;*/
/*flex: 1;*/
/*padding: rpx(24) rpx(30);*/
/*width: 90%;*/
/*display: flex;*/
/*flex: 1;*/
/*height: rpx(400);*/
/*padding: rpx(28) rpx(14) rpx(14);*/
padding: 10px;
position: relative;
}
.c-recall-card__body {
background: #fff;
box-sizing: border-box;
overflow: hidden;
/*box-shadow: 0 0 1px 1px rgba(0,0,0,0.05), 0 2px 2px 0 rgba(0,0,0,0.10);*/
border-radius: 4px;
padding: 14px 10px 7px;
position: relative;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
}
.c-recall-card__content {
box-sizing: border-box;
padding: 10px;
height: 138px;
width: 100%;
/*box-shadow: 0 0 1px 1px rgba(0,0,0,0.05),0 2px 2px 0 rgba(0,0,0,0.08);*/
}
.c-recall-card__warpper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
align-self: center;
justify-self: center;
}
.c-recall__content {
flex: 1;
width: inherit;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
align-self: center;
justify-self: center;
}
.c-recall__meta {
/*position: absolute;*/
/*bottom: 10px;*/
/*padding: 0 10px 0 10px;*/
box-sizing: border-box;
/*width: rpx(600);*/
/*text-align: right;*/
/*font-size: rpx(36);*/
display: block;
line-height: 1.615;
/*font-weight: 300;*/
/*width: rpx(620);*/
width: 100%;
/*text-align: center;*/
}
.c-swiper__item {
width: 100% !important;
}
.c-replies {
position: relative;
margin-bottom: 60px;
}
.c-write-button {
display: flex;
align-items: center;
color: #985ED6;
padding-left: 15px;
font-size: 14px;
justify-items: end;
float: right;
background: none;
}
</style>
<template>
<scroll-view :scroll-y="isScroll"
:style="style">
<div class="o-page"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend" v-if="detail.id">
<div class="c-special__cover">
<image
:src="detail.featured_image"
mode="aspectFill" :style="coverStyle">
</image>
</div>
<div class="c-panel">
<div class="c-cell c-special__author" v-if="detail.author">
<image class="c-avatar c-cell__icon" :src="detail.author.avatarUrl"></image>
<div class="c-cell__bd">
<div class="c-special__author-info">
<span>{{detail.author.user_nicename}}</span>
<span class="c-special__author-info__highlights" v-if="hasResume">{{detail.author.resume.highlights}}</span>
</div>
</div>
<div class="c-cell__ft"></div>
</div>
</div>
<div class="c-panel-title u-flex u-justify-between" v-if="hasResume">
<span class="u-text-large u-text-dark u-text-bold">介绍</span>
<span @click="toggleContent" class="u-c-blue">{{contentTitle}}</span>
</div>
<div :class="['c-panel animated fadeIn', {'fadeOut': !showContent}]" v-show="showContent">
<div class="u-p-medium " v-if="detail.content">
{{detail.content}}
</div>
</div>
<div class="c-panel-title u-flex u-justify-between">
<span class="u-text-large u-text-dark u-text-bold">内容</span>
<span class="u-flex u-justify-end u-align-items-center u-c-blue" @click="playAll">
<image class="u-icon-medium u-mr-small"
:src="audioStatus === 'playing' ? '/static/images/pause_big.png' : '/static/images/play_big.png'"></image>
全部
</span>
</div>
<div class="c-panel">
<div class="c-cell c-cell--access"
:id="'block-' + item.id"
v-for="(item, index) of detail.block"
:key="item.id"
@click="playItem(item, index)">
<div class="c-cell__icon">
<play-button :index="index + 1"
:current="curAudio.id === item.id"
:status="audioStatus"/>
</div>
<div class="c-cell__bd">
<div class="c-cell__text" style="font-size: 15px;"> {{item.title}}</div>
<div class="c-cell__desc u-text-mute">{{item.date}}</div>
</div>
</div>
</div>
<div class="c-replies " id="comments">
<div class="c-panel-title u-flex u-justify-between">
<span class="u-text-large u-text-dark u-text-bold">评价</span>
<span>({{repliesPage}})</span>
</div>
<div v-if="hasComments">
<swiper style="height: 210px;" @change="bindSwiperChange">
<swiper-item class="c-swiper__item"
v-for="(item, index) in replies.data"
:key="item.id">
<comment-card :comment="item"/>
</swiper-item>
</swiper>
</div>
<div style="height: 210px;" class="u-flex u-align-items-center u-justify-center u-text-center" v-else>
暂无评价
</div>
<button class=" c-btn c-btn--flat c-write-button" @click="handleAddComment">
<span class="u-ml-small u-mr-small">写评价</span>
<image class="u-icon-small" src="/static/images/pencil.png"></image>
</button>
</div>
<player
v-model="showPlayer"
@show-list="handleShowPlayList"
@comment="handleAddComment"/>
</div>
<div class="u-flex u-justify-center u-align-items-center u-height-100" style="background: #fff;" v-else>
<button class="c-btn c-btn--flat c-btn--large c-btn--loading"></button>
</div>
</scroll-view>
</template>
<script>
import postsApi from '@/api/posts'
import Player from '@/components/player'
import CommentCard from '@/components/comment-card'
import SliderPanel from '@/components/slider-panel'
import PlayButton from '@/components/play-button'
import {mapState, mapActions} from 'vuex'
const device = wx.getSystemInfoSync() // 获取设备信息
const dataArr = []
export default {
components: {
Player,
CommentCard,
SliderPanel,
PlayButton
},
data () {
return {
detail: {},
replies: {
data: []
},
coverWidth: device.windowWidth,
isSliderDisplay: false,
isSliderModal: true,
isScroll: true,
current: 0,
showContent: true,
showPlayer: false,
direction: 'X',
touchStartY: 0,
translateY: 0,
position: 40,
currentGesture: 0
}
},
computed: {
...mapState([
'print',
'audio'
]),
hasResume () {
if (!Object.is(this.detail.author, undefined)) {
const _author = this.detail.author
return !Object.is(_author.resume, undefined)
}
return false
},
style () {
return `height: ${device.windowHeight + 100}px;`
},
/**
* @return {string}
*/
XORY () {
return this.direction === 'horizontal' ? 'X' : 'Y'
},
rectDistance () {
return this.direction === 'horizontal' ? this.width : this.height
},
audioStatus () {
return this.$audioStore.state.status
},
curAudio () {
return this.$audio.getAudio()
},
coverStyle () {
return `width: ${this.coverWidth}px;height: 200px;`
},
repliesPage () {
if (this.replies && !Object.is(this.replies.data, undefined)) {
const page = this.current + 1
return `${page}/${this.replies.data.length}`
} else {
return ''
}
},
repliesTitle () {
if (this.replies && !Object.is(this.replies.data, undefined)) {
return `${this.replies.data.length} 条点评`
} else {
return '还没有点评'
}
},
contentTitle () {
return this.showContent ? '隐藏' : '显示'
},
hasComments () {
// if (!Object.is(this.replies.data.length, undefined)) {
// return true
// }
return this.replies.data.length > 0
}
},
methods: {
handleShowPlayList (show) {
this.isScroll = !show
},
touchstart (e) {
let touch = null
if (e.mp !== undefined) {
touch = e.mp.changedTouches[0]
} else {
touch = e.changedTouches[0]
}
const distance = touch.pageY // startPos
this.touchStartY = distance
},
touchmove (e) {
if (this.currentGesture !== 0) {
return
}
let touch = null
if (e.mp !== undefined) {
touch = e.mp.changedTouches[0]
// this.startX = e.mp.touches[0].clientX
} else {
touch = e.changedTouches[0]
// this.startX = e.touches[0].clientX
}
let currentY = touch.pageY
let ty = currentY - this.touchStartY
if (ty < 0) {
this.currentGesture = 1
this.showPlayer = false
} else {
this.currentGesture = 2
this.showPlayer = true
}
this.touchStartY = currentY
},
touchend (e) {
this.currentGesture = 0
},
initAlbum () {
// SET Album
if (this.$audio.getAlbum().id !== this.detail.id) {
this.$audio.setAlbum({
id: this.detail.id,
title: this.detail.title,
epname: this.detail.title,
singer: this.detail.author,
list: this.detail.block,
description: this.detail.content,
coverImgUrl: this.detail.featured_image,
webUrl: `/pages/detail?id=${this.detail.id}`
})
}
},
playAll () {
this.showPlayer = true
this.initAlbum()
this.$audio.play()
},
playItem (item) {
this.showPlayer = true
if (Object.is(item.featured_image, undefined)) {
// coverImgUrl
item.featured_image = this.detail.featured_image
}
this.initAlbum()
// Control Audio
if (this.$audio.getAudio().id !== item.id) {
const curAudio = {
id: item.id,
albumId: this.detail.id,
epname: this.detail.title,
title: item.title,
singer: item.author.user_nicename,
avatar: item.author.avatar,
coverImgUrl: this.detail.featured_image,
src: item.url
}
this.$audio.setAudio(curAudio)
this.$audio.playTarget()
}
this.$audio.play()
},
toggleContent () {
this.showContent = !this.showContent
},
async getDetail (id) {
this.detail = await postsApi.detail(id)
},
async getReplies (id) {
this.replies = await postsApi.getReplies(id)
},
bindSwiperChange (e) {
this.current = e.target.current
},
handleAddComment (e) {
// const url = `/pages/comment?postId=${this.detail.id}&title=${this.detail.title}`
// wx.navigateTo({url})
this.$router.push({
path: "/pages/comment",
query: {
postId: this.detail.id,
title: this.detail.title
}
});
},
async view(id) {
await postsApi.newView(id)
}
},
mounted () {
Object.assign(this.$data, this.$options.data())
const query = this.$root.$mp.query
if (!query.id) {
return
}
this.showPlayer = false
this.getDetail(query.id)
this.getReplies(query.id)
this.view(query.id)
},
async onLoad () {
},
onUnload () {
dataArr.pop()
const dataNum = dataArr.length
if (!dataNum) return
Object.assign(this.$data, dataArr[dataNum - 1])
}
}
</script>
code
<style lang="scss">
@import "../scss/variable";
Page, .body {
font-size: 14px;
color: #333333;
background: #F5F5F7;
}
.c-topbar {
position: fixed;
top: 0;
background: #FFF;
/*border-bottom-right-radius: rpx(32);*/
/*border-bottom-left-radius: rpx(32);*/
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.10);
height: rpx(100);
width: 100%;
z-index: 3;
}
.c-category {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 33.33333%;
height: 100px;
float: left;
text-align: center;
}
/*.icon-classname {*/
/*color: #999;*/
/*font-size: 10px;*/
/*}*/
.c-category__icon {
width: rpx(64);
height: rpx(64);
margin-bottom: rpx(20);
}
.c-section__title {
font-size: 18px;
position: relative;
}
.c-popular {
display: flex;
width: 100%;
height: 100%;
flex-wrap: wrap;
justify-content: center;
align-items: center;
/*flex-direction: column;*/
flex-direction: row;
/*box-sizing: border-box;*/
}
.c-popular-card {
display: inline-block;
/*vertical-align: middle;*/
overflow: hidden;
position: relative;
/*flex: 1;*/
padding: 7px 5px 7px;
/*padding: rpx(24) rpx(30);*/
box-sizing: border-box;
}
.c-popular-card--isHover {
/*background: #FF7058;*/
> .c-love-card__body {
box-shadow: none;
background: #FF7058;
color: #fff;
transition: color .2s ease-in, -webkit-transform .15s cubic-bezier(.175, .885, .32, 1.275);
> .c-love-card__detail {
color: rgba(255, 255, 255, 0.80);
}
}
}
.c-popular-card__body {
display: flex;
flex: 1;
background: #FBFBFB;
position: relative;
text-align: left;
flex-direction: column;
box-sizing: border-box;
width: 168px;
height: 110px;
padding: 10px;
}
.c-popular-card__title {
font-size: 15px;
font-weight: 400;
width: 100%;
flex: 1;
text-align: left;
}
.c-popular-card__detail {
margin: 0 0 rpx(28);
font-size: rpx(26);
font-weight: 400;
color: rgba(31, 31, 31, 0.50);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.0769231;
}
.c-popular-card__cover {
position: absolute;
left: rpx(20);
right: rpx(20);
bottom: rpx(20);
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.08);
width: auto;
height: rpx(240);
}
.c-popular-card__footer {
flex: 1;
align-items: center;
/*justify-content: end;*/
display: flex;
flex-direction: row;
&-author {
align-items: center;
flex: 1;
flex-direction: row;
display: flex;
align-items: center;
/*justify-content: center;*/
}
&-action {
align-items: center;
/*flex: 1;*/
}
}
.c-news {
}
</style>
<template>
<div>
<div style="position: relative; height: 280px;">
<div style="display: flex; flex-direction: column; align-items: center;" class="u-m-large">
<image class="c-icon icon-band" :src="detail.featured_image" mode="aspectFit"> </image>
<div class="c-section__title u-mt-medium">
{{detail.name}}
</div>
</div>
<div class="c-news u-mb-medium">
<div class="c-panel c-panel--without-margin-top"
v-for="(item, index) in page.list" :key="item.id">
<div class="c-card" @click="showDetail(item.id)">
<div class="c-card__thumb">
<image class="c-card__img" :src="item.featured_image"
mode="aspectFit"></image>
</div>
<div class="c-card__detail u-mt-medium">
<view class="c-card__detail-row">
<view class=" ">
{{item.title}}
</view>
</view>
</div>
<view class="c-card__detail u-mt-small u-text-mute" style="font-weight: 300;">
<view class="c-card__right-col ">
{{item.modified}}
</view>
<view class="c-card__left-col">{{item.like_count}} 人喜欢</view>
</view>
</div>
</div>
</div>
<play-fab />
<Loadmore :page.sync="page"/>
</div>
</div>
</template>
<script>
import wx from 'wx'
import {mapState, mapActions} from 'vuex'
import AdSwiper from '@/components/ad-swiper'
import Loadmore from '@/components/loadmore'
import auth from '@/api/auth'
import pagination from '@/mixins/pagination'
import postApi from '@/api/posts'
import PlayFab from '@/components/play-fab'
export default {
mixins: [pagination],
data () {
return {
motto: 'Hello World',
userInfo: {},
page: {
reachBottom: false,
added: [],
list: []
},
slug: ''
}
},
components: {
AdSwiper,
Loadmore,
PlayFab
},
onLoad () {
const query = this.$root.$mp.query
this.slug = query.slug
if (!this.slug) {
return
}
this.getPageList()
},
computed: {
...mapState([
'app',
'categories'
]),
detail () {
const category = this.categories.find((cate) => {
if (cate.slug === this.slug) {
return cate
}
})
return category
}
},
methods: {
showDetail (id) {
console.log('CATEgory-----' + id)
this.$router.push({
path: "/pages/detail",
query: {
id: id
}
});
// wx.navigateTo({
// url: `/pages/detail?id=${id}`
// })
},
async getPageList () {
this.page = await postApi.page(this.slug)
await this.next()
}
}
}
</script>
<style lang="scss">
Page, body {
/*background: #F5F5F7;*/
font-size: 15px;
color: #2d3848;
line-height: 26px;
letter-spacing: 1.25px;
width: 100%;
height: 100%;
}
.o-page {
display: flex;
flex-direction: column;
textarea {
padding: 15px;
width: 95%;
height: 200px;
margin-left: auto;
margin-right: auto;
font-size: 16px;
line-height: 1.5;
letter-spacing: 1.25px;
border-radius: 4px;
box-sizing: border-box;
}
}
.c-page__cover {
z-index: 1;
height: 200px;
position: relative;
display: flex;
flex-direction: column;
}
.c-page__body {
display: flex;
}
.c-section__title {
font-size: 16px;
}
.c-love-special {
background: #F5F5F7;
}
.c-special__cover {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
}
.c-special__author {
background: #fff;
display: flex;
flex-direction: row;
align-items: center;
/*padding: 20px;*/
padding-top: 20px;
.c-avatar {
width: 56px;
height: 56px;
}
&-info {
font-size: 16px;
padding-left: 10px;
display: flex;
flex-direction: column;
align-items: start;
line-height: 24px;
&__highlights {
font-size: 14px;
font-weight: 300;
}
}
}
.c-author__info {
display: flex;
flex-direction: column;
align-items: start;
}
.c-special__detail {
padding: 20px;
}
.replies {
&__header {
}
/*display: flex;*/
/*flex-direction: column;*/
&__list {
}
&__item {
padding: 20px;
display: flex;
flex-direction: row;
align-items: flex-start;
&-user {
display: flex;
height: auto;
&--avatar {
width: 36px;
height: 36px;
background-position: center center;
border-radius: 50px;
border: 2px solid #efefef;
}
}
&-info {
flex: 1;
margin-left: 15px;
&__nicename {
font-weight: 300;
display: inline-flex;
}
&--date {
float: right;
color: #D1D1D1;
font-weight: 300;
font-size: 12px;
}
&__content {
/*color: #7f8fa4;*/
color: #2d3848;
}
}
}
}
.c-placeholder {
transition: opacity 0.3s;
color: #fff;
opacity: 0.65;
}
.c-love-card--isHover {
}
.c-recalls--scroll {
display: flex;
white-space: nowrap;
width: rpx(780);
}
.c-recall-card {
/*box-sizing:border-box;*/
/*display: flex;*/
/*flex: 1;*/
/*height: rpx(360);*/
/*background: #fff;*/
/*box-shadow: 0 0 1px 1px rgba(0,0,0,0.05), 0 2px 2px 0 rgba(0,0,0,0.10);*/
/*border-radius: rpx(8);*/
/*padding: rpx(28) rpx(20) rpx(14);*/
/*position: relative;*/
/*align-items: center;*/
/*flex-direction: column;*/
/*position: relative;*/
/*flex: 1;*/
/*padding: rpx(24) rpx(30);*/
/*width: 90%;*/
/*display: flex;*/
/*flex: 1;*/
/*height: rpx(400);*/
/*padding: rpx(28) rpx(14) rpx(14);*/
padding: 10px;
position: relative;
}
.c-recall-card__body {
background: #fff;
box-sizing: border-box;
overflow: hidden;
/*box-shadow: 0 0 1px 1px rgba(0,0,0,0.05), 0 2px 2px 0 rgba(0,0,0,0.10);*/
border-radius: 4px;
padding: 14px 10px 7px;
position: relative;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
}
.c-recall-card__content {
box-sizing: border-box;
padding: 10px;
height: 138px;
width: 100%;
/*box-shadow: 0 0 1px 1px rgba(0,0,0,0.05),0 2px 2px 0 rgba(0,0,0,0.08);*/
}
.c-recall-card__warpper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
align-self: center;
justify-self: center;
}
.c-recall__content {
flex: 1;
width: inherit;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
align-self: center;
justify-self: center;
}
.c-recall__meta {
/*position: absolute;*/
/*bottom: 10px;*/
/*padding: 0 10px 0 10px;*/
box-sizing: border-box;
/*width: rpx(600);*/
/*text-align: right;*/
/*font-size: rpx(36);*/
display: block;
line-height: 1.615;
/*font-weight: 300;*/
/*width: rpx(620);*/
width: 100%;
/*text-align: center;*/
}
.c-swiper__item {
/*wx-swiper-item {*/
width: 100% !important;
/*margin-left: 5% !important;*/
}
.c-replies {
position: relative;
margin-bottom: 60px;
}
.c-write-button {
display: flex;
align-items: center;
color: #985ED6;
padding-left: 15px;
font-size: 14px;
justify-items: end;
flat: right;
}
</style>
<template>
<div class="o-page">
<form @submit="formSubmit" report-submit="true">
<div class="c-panel c-panel--without-margin-top u-flex u-justify-between u-align-items-center u-p-small">
<button class="c-btn c-btn--flat c-btn--small u-text-bold" @click="cancel">取消</button>
<!--<color-button :rgb="selectedColor.RGB" @toggle="changeColor"/>-->
<color-button :rgb="selectedColor.RGB" @toggle="changeColor"/>
<button formType="submit"
:class="['c-btn c-btn--small u-text-bold c-btn--flat c-btn--primary',{
'c-btn--loading': isPost,
'c-btn--disabled': isEmpty
}]"
:disabled="isEmpty || isPost">
<span v-if="!isPost">发布</span>
</button>
<!--<div class="c-btn c-btn--flat c-btn--small u-c-cyan">发送</div>-->
</div>
<div style="position: fixed; top: 50px; width: 100%;">
<textarea class="u-mt-small u-pl-medium"
@input="bindInput"
@focus="bindFocus"
@blur="bindBlur"
:focus="autoFocus"
placeholder="在这里写下您的评价"
:placeholder-style="selectedColor.dark"
maxlength="141"
:style="selectedColor.dark"
fixed="true"></textarea>
<div
class="c-panel c-panel--without-margin-top c-panel--without-border u-flex u-justify-between u-m-small">
<span class="u-c-gray u-text-small">
剩余 {{140 - wordCount}} 个字
</span>
</div>
</div>
</form>
<slider-color-panel
:isModal="isSliderModal"
@change-color="handleSelectdColor"
v-model="isSliderDisplay">
<div slot="title">
个性化
</div>
</slider-color-panel>
<c-dialog v-model="dialog"/>
</div>
</template>
<script>
import BaseMixins from '@/mixins/base'
import postsApi from '@/api/posts'
import SliderColorPanel from '@/components/slider-color-panel'
import ColorButton from '@/components/color-button'
import CDialog from '@/components/dialog'
import Tips from '@/utils/tips'
import Route from '@/utils/WxUtils'
const device = wx.getSystemInfoSync() // 获取设备信息
export default {
mixins: [BaseMixins],
components: {
SliderColorPanel,
ColorButton,
CDialog
},
data () {
return {
postId: 1,
detail: {},
replies: {},
coverWidth: device.windowWidth,
current: 0,
isSliderDisplay: false,
isSliderModal: false,
autoFocus: true,
colors: [
{
'RGB': [
48,
48,
48
],
'hex': '#303030',
'name': '百草霜',
'pinyin': 'baicaoshuang'
},
{
'RGB': [
78,
24,
146
],
'hex': '#4e1892',
'name': '柏坊灰蓝',
'pinyin': 'baifanghuilan'
},
{
'RGB': [
31,
54,
150
],
'hex': '#1f3696',
'name': '宝蓝',
'pinyin': 'baolan'
},
{
'RGB': [
39,
104,
147
],
'hex': '#276893',
'name': '北京毛蓝',
'pinyin': 'beijingmaolan'
},
{
'RGB': [
86,
149,
151
],
'hex': '#569597',
'name': '碧玉石',
'pinyin': 'biyushi'
},
{
'RGB': [
198,
83,
6
],
'hex': '#c65306',
'name': '苍黄',
'pinyin': 'canghuang'
},
{
'RGB': [
37,
56,
107
],
'hex': '#25386b',
'name': '藏蓝',
'pinyin': 'zanglan'
},
{
'RGB': [
78,
95,
69
],
'hex': '#4e5f45',
'name': '苍绿',
'pinyin': 'canglyu'
},
{
'RGB': [
219,
206,
84
],
'hex': '#dbce54',
'name': '草黄',
'pinyin': 'caohuang'
},
{
'RGB': [
117,
117,
112
],
'hex': '#757570',
'name': '承德灰',
'pinyin': 'chengdehui'
},
{
'RGB': [
90,
92,
91
],
'hex': '#5a5c5b',
'name': '承德皂',
'pinyin': 'chengdezao'
},
{
'RGB': [
175,
94,
83
],
'hex': '#af5e53',
'name': '辰砂',
'pinyin': 'chensha'
},
{
'RGB': [
123,
161,
168
],
'hex': '#7ba1a8',
'name': '春蓝',
'pinyin': 'chunlan'
},
{
'RGB': [
227,
239,
209
],
'front': '#006e5f',
'hex': '#e3efd1',
'name': '春绿',
'pinyin': 'chunlyu'
},
{
'RGB': [
0,
110,
95
],
'hex': '#006e5f',
'name': '翠绿',
'pinyin': 'cuilyu'
},
{
'RGB': [
67,
69,
74
],
'hex': '#43454a',
'name': '粗晶皂',
'pinyin': 'cujingzao'
},
{
'RGB': [
109,
115,
88
],
'hex': '#6d7358',
'name': '大赤金',
'pinyin': 'dachijin'
},
{
'RGB': [
48,
71,
88
],
'hex': '#304758',
'name': '黛蓝',
'pinyin': 'dailan'
},
{
'RGB': [
215,
193,
107
],
'hex': '#d7c16b',
'name': '丹东石',
'pinyin': 'dandongshi'
},
{
'RGB': [
174,
196,
183
],
'hex': '#aec4b7',
'name': '淡灰绿',
'pinyin': 'danhuilyu'
},
{
'RGB': [
54,
53,
50
],
'hex': '#363532',
'name': '灯草灰',
'pinyin': 'dengcaohui'
},
{
'RGB': [
27,
84,
242
],
'hex': '#1b54f2',
'name': '靛蓝',
'pinyin': 'dianlan'
},
{
'RGB': [
196,
71,
61
],
'hex': '#c4473d',
'name': '蕃茄红',
'pinyin': 'fanqiehong'
},
{
'RGB': [
195,
86,
85
],
'hex': '#c35655',
'name': '妃红',
'pinyin': 'feihong'
},
{
'RGB': [
228,
207,
142
],
'hex': '#e4cf8e',
'name': '甘草黄',
'pinyin': 'gancaohuang'
},
{
'RGB': [
106,
104,
52
],
'hex': '#6a6834',
'name': '橄榄绿',
'pinyin': 'ganlanlyu'
},
{
'RGB': [
234,
220,
214
],
'front': '#344A5E',
'hex': '#eadcd6',
'name': '甘石粉',
'pinyin': 'ganshifen'
},
{
'RGB': [
100,
147,
175
],
'hex': '#6493af',
'name': '钴蓝',
'pinyin': 'gulan'
},
{
'RGB': [
136,
174,
163
],
'hex': '#88aea3',
'name': '果灰',
'pinyin': 'guohui'
},
{
'RGB': [
23,
80,
125
],
'hex': '#17507d',
'name': '海蓝',
'pinyin': 'hailan'
},
{
'RGB': [
79,
83,
85
],
'hex': '#4f5355',
'name': '红皂',
'pinyin': 'hongzao'
},
{
'RGB': [
176,
183,
172
],
'hex': '#b0b7ac',
'name': '黄灰',
'pinyin': 'huanghui'
},
{
'RGB': [
84,
107,
131
],
'hex': '#546b83',
'name': '花青',
'pinyin': 'huaqing'
},
{
'RGB': [
93,
130,
138
],
'hex': '#5d828a',
'name': '灰蓝',
'pinyin': 'huilan'
},
{
'RGB': [
92,
137,
135
],
'hex': '#5c8987',
'name': '灰绿',
'pinyin': 'huilyu'
},
{
'RGB': [
182,
177,
150
],
'hex': '#b6b196',
'name': '灰米',
'pinyin': 'huimi'
},
{
'RGB': [
180,
148,
54
],
'hex': '#b49436',
'name': '姜黄',
'pinyin': 'jianghuang'
},
{
'RGB': [
109,
97,
74
],
'hex': '#6d614a',
'name': '将校呢',
'pinyin': 'jiangxiaoni'
},
{
'RGB': [
112,
77,
78
],
'hex': '#704d4e',
'name': '绛紫',
'pinyin': 'jiangzi'
},
{
'RGB': [
231,
105,
63
],
'hex': '#e7693f',
'name': '桔红',
'pinyin': 'jiehong'
},
{
'RGB': [
232,
133,
59
],
'hex': '#e8853b',
'name': '桔黄',
'pinyin': 'jiehuang'
},
{
'RGB': [
199,
122,
58
],
'hex': '#c77a3a',
'name': '金黄',
'pinyin': 'jinhuang'
},
{
'RGB': [
202,
212,
186
],
'hex': '#cad4ba',
'name': '军绿',
'pinyin': 'junlyu'
},
{
'RGB': [
0,
65,
165
],
'hex': '#0041a5',
'name': '孔雀蓝',
'pinyin': 'kongquelan'
},
{
'RGB': [
133,
121,
79
],
'hex': '#85794f',
'name': '库金',
'pinyin': 'kujin'
},
{
'RGB': [
183,
178,
120
],
'hex': '#b7b278',
'name': '枯绿',
'pinyin': 'kulyu'
},
{
'RGB': [
231,
229,
208
],
'front': '#344A5E',
'hex': '#e7e5d0',
'name': '蜡白',
'pinyin': 'labai'
},
{
'RGB': [
61,
110,
83
],
'hex': '#3d6e53',
'name': '老绿',
'pinyin': 'laolyu'
},
{
'RGB': [
213,
75,
68
],
'hex': '#d54b44',
'name': '榴花红',
'pinyin': 'liuhuahong'
},
{
'RGB': [
169,
176,
143
],
'hex': '#a9b08f',
'name': '芦灰',
'pinyin': 'luhui'
},
{
'RGB': [
151,
52,
68
],
'hex': '#973444',
'name': '玫瑰红',
'pinyin': 'meiguihong'
},
{
'RGB': [
121,
61,
86
],
'hex': '#793d56',
'name': '玫瑰灰',
'pinyin': 'meiguihui'
},
{
'RGB': [
225,
189,
162
],
'hex': '#e1bda2',
'name': '米红',
'pinyin': 'mihong'
},
{
'RGB': [
197,
191,
173
],
'hex': '#c5bfad',
'name': '米灰',
'pinyin': 'mihui'
},
{
'RGB': [
245,
245,
220
],
'custom': '#344A5E',
'hex': '#f5f5dc',
'name': '米色',
'pinyin': 'mise'
},
{
'RGB': [
175,
200,
186
],
'custom': '#344A5E',
'hex': '#afc8ba',
'name': '奶绿',
'pinyin': 'nailyu'
},
{
'RGB': [
193,
162,
153
],
'hex': '#c1a299',
'name': '奶棕',
'pinyin': 'naizong'
},
{
'RGB': [
233,
219,
57
],
'hex': '#e9db39',
'name': '柠檬黄',
'pinyin': 'ningmenghuang'
},
{
'RGB': [
167,
19,
104
],
'hex': '#a71368',
'name': '品红',
'pinyin': 'pinhong'
},
{
'RGB': [
60,
94,
145
],
'hex': '#3c5e91',
'name': '浅海昌蓝',
'pinyin': 'qianhaichanglan'
},
{
'RGB': [
222,
168,
122
],
'hex': '#dea87a',
'name': '浅黄棕',
'pinyin': 'qianhuangzong'
},
{
'RGB': [
218,
149,
88
],
'hex': '#da9558',
'name': '浅桔黄',
'pinyin': 'qianjiehuang'
},
{
'RGB': [
162,
32,
118
],
'hex': '#a22076',
'name': '牵牛紫',
'pinyin': 'qianniuzi'
},
{
'RGB': [
171,
150,
197
],
'hex': '#ab96c5',
'name': '浅石英紫',
'pinyin': 'qianshiyingzi'
},
{
'RGB': [
196,
195,
203
],
'hex': '#c4c3cb',
'name': '浅藤紫',
'pinyin': 'qiantengzi'
},
{
'RGB': [
201,
174,
140
],
'hex': '#c9ae8c',
'name': '浅驼色',
'pinyin': 'qiantuose'
},
{
'RGB': [
234,
205,
209
],
'hex': '#eacdd1',
'name': '浅血牙',
'pinyin': 'qianxieya'
},
{
'RGB': [
225,
219,
205
],
'hex': '#e1dbcd',
'name': '浅棕灰',
'pinyin': 'qianzonghui'
},
{
'RGB': [
213,
184,
132
],
'hex': '#d5b884',
'name': '卡其黄',
'pinyin': 'kaqihuang'
},
{
'RGB': [
100,
115,
112
],
'hex': '#647370',
'name': '卡其绿',
'pinyin': 'kaqilyu'
},
{
'RGB': [
103,
73,
80
],
'hex': '#674950',
'name': '茄皮紫',
'pinyin': 'qiepizi'
},
{
'RGB': [
69,
86,
103
],
'hex': '#455667',
'name': '鹊灰',
'pinyin': 'quehui'
},
{
'RGB': [
49,
103,
141
],
'hex': '#31678d',
'name': '绒蓝',
'pinyin': 'ronglan'
},
{
'RGB': [
144,
202,
175
],
'hex': '#90caaf',
'name': '三绿',
'pinyin': 'sanlyu'
},
{
'RGB': [
0,
91,
90
],
'hex': '#005b5a',
'name': '沙绿',
'pinyin': 'shalyu'
},
{
'RGB': [
43,
94,
125
],
'hex': '#2b5e7d',
'name': '沙青',
'pinyin': 'shaqing'
},
{
'RGB': [
90,
76,
76
],
'hex': '#5a4c4c',
'name': '深烟',
'pinyin': 'shenyan'
},
{
'RGB': [
100,
52,
65
],
'hex': '#643441',
'name': '深烟红',
'pinyin': 'shenyanhong'
},
{
'RGB': [
37,
120,
181
],
'hex': '#2578b5',
'name': '深竹月',
'pinyin': 'shenzhuyue'
},
{
'RGB': [
252,
177,
170
],
'hex': '#fcb1aa',
'name': '十样锦',
'pinyin': 'shiyangjin'
},
{
'RGB': [
148,
156,
151
],
'hex': '#949c97',
'name': '水貂灰',
'pinyin': 'shuidiaohui'
},
{
'RGB': [
190,
210,
182
],
'hex': '#bed2b6',
'name': '水黄',
'pinyin': 'shuihuang'
},
{
'RGB': [
242,
222,
118
],
'hex': '#f2de76',
'name': '藤黄',
'pinyin': 'tenghuang'
},
{
'RGB': [
46,
195,
231
],
'hex': '#2ec3e7',
'name': '天青',
'pinyin': 'tianqing'
},
{
'RGB': [
55,
68,
75
],
'hex': '#37444b',
'name': '铁灰',
'pinyin': 'tiehui'
},
{
'RGB': [
206,
147,
53
],
'hex': '#ce9335',
'name': '土黄',
'pinyin': 'tuhuang'
},
{
'RGB': [
98,
92,
82
],
'hex': '#625c52',
'name': '相思灰',
'pinyin': 'xiangsihui'
},
{
'RGB': [
160,
62,
40
],
'hex': '#a03e28',
'name': '血红',
'pinyin': 'xiehong'
},
{
'RGB': [
196,
55,
57
],
'hex': '#c43739',
'name': '猩红',
'pinyin': 'xinghong'
},
{
'RGB': [
208,
133,
61
],
'hex': '#d0853d',
'name': '雄黄',
'pinyin': 'xionghuang'
},
{
'RGB': [
228,
117,
66
],
'hex': '#e47542',
'name': '雄精',
'pinyin': 'xiongjing'
},
{
'RGB': [
77,
25,
25
],
'hex': '#4d1919',
'name': '锈红',
'pinyin': 'xiuhong'
},
{
'RGB': [
184,
200,
183
],
'hex': '#b8c8b7',
'name': '锈绿',
'pinyin': 'xiulyu'
},
{
'RGB': [
121,
111,
84
],
'hex': '#796f54',
'name': '选金',
'pinyin': 'xuanjin'
},
{
'RGB': [
255,
250,
250
],
'front': '#344A5E',
'hex': '#fffafa',
'name': '雪色',
'pinyin': 'xuese'
},
{
'RGB': [
121,
72,
90
],
'hex': '#79485a',
'name': '雪紫',
'pinyin': 'xuezi'
},
{
'RGB': [
209,
227,
219
],
'hex': '#d1e3db',
'name': '鸭蛋青',
'pinyin': 'yadanqing'
},
{
'RGB': [
156,
102,
128
],
'hex': '#9c6680',
'name': '洋葱紫',
'pinyin': 'yangcongzi'
},
{
'RGB': [
220,
20,
60
],
'hex': '#dc143c',
'name': '洋红',
'pinyin': 'yanghong'
},
{
'RGB': [
204,
53,
54
],
'hex': '#cc3536',
'name': '艳红',
'pinyin': 'yanhong'
},
{
'RGB': [
0,
142,
89
],
'hex': '#008e59',
'name': '鹦鹉绿',
'pinyin': 'yingwulyu'
},
{
'RGB': [
221,
59,
68
],
'hex': '#dd3b44',
'name': '银朱',
'pinyin': 'yinzhu'
},
{
'RGB': [
69,
85,
74
],
'hex': '#45554a',
'name': '油绿',
'pinyin': 'youlyu'
},
{
'RGB': [
63,
63,
60
],
'hex': '#3f3f3c',
'name': '油烟墨',
'pinyin': 'youyanmo'
},
{
'RGB': [
62,
60,
61
],
'hex': '#3e3c3d',
'name': '元青',
'pinyin': 'yuanqing'
},
{
'RGB': [
192,
63,
60
],
'hex': '#c03f3c',
'name': '胭脂',
'pinyin': 'yanzhi'
},
{
'RGB': [
88,
90,
87
],
'hex': '#585a57',
'name': '银箔',
'pinyin': 'yinbo'
},
{
'RGB': [
187,
28,
51
],
'hex': '#bb1c33',
'name': '月季红',
'pinyin': 'yuejihong'
},
{
'RGB': [
80,
120,
131
],
'hex': '#507883',
'name': '玉石蓝',
'pinyin': 'yushilan'
},
{
'RGB': [
137,
48,
63
],
'hex': '#89303f',
'name': '枣红',
'pinyin': 'zaohong'
},
{
'RGB': [
235,
101,
45
],
'hex': '#eb652d',
'name': '章丹',
'pinyin': 'zhangdan'
},
{
'RGB': [
147,
162,
169
],
'hex': '#93a2a9',
'name': '正灰',
'pinyin': 'zhenghui'
},
{
'RGB': [
219,
199,
166
],
'hex': '#dbc7a6',
'name': '枝黄',
'pinyin': 'zhihuang'
},
{
'RGB': [
116,
138,
141
],
'hex': '#748a8d',
'name': '织锦灰',
'pinyin': 'zhijinhui'
},
{
'RGB': [
188,
165,
144
],
'hex': '#bca590',
'name': '纸棕',
'pinyin': 'zhizong'
},
{
'RGB': [
169,
152,
124
],
'hex': '#a9987c',
'name': '中棕灰',
'pinyin': 'zhongzonghui'
},
{
'RGB': [
165,
67,
88
],
'hex': '#a54358',
'name': '紫粉',
'pinyin': 'zifen'
},
{
'RGB': [
195,
166,
203
],
'hex': '#c3a6cb',
'name': '紫水晶',
'pinyin': 'zishuijing'
},
{
'RGB': [
133,
126,
149
],
'hex': '#857e95',
'name': '紫藤灰',
'pinyin': 'zitenghui'
},
{
'RGB': [
238,
165,
209
],
'hex': '#eea5d1',
'name': '紫薇花',
'pinyin': 'ziweihua'
},
{
'RGB': [
184,
132,
79
],
'hex': '#b8844f',
'name': '棕茶',
'pinyin': 'zongcha'
}
],
randomColors: [],
selectedColor: {
'RGB': [
98,
92,
82
],
'hex': '#625c52',
'name': '相思灰',
'pinyin': 'xiangsihui'
},
isFocus: false,
content: '',
title: '',
isPost: false
}
},
computed: {
wordCount () {
return this._wordCount(this.content)
},
isEmpty () {
return this.content.trim().length === 0 || this.content === '' || this.content === null || this.content === undefined
},
buttonClass () {
// class="c-btn c-btn--flat c-btn--small u-text-bold {{isPost ? 'c-btn--loading' : ' u-c-cyan'}} {{isEmpty ? 'c-btn--disabled' : ''}}
return [
'c-btn c-btn--flat c-btn--small u-text-bold',
{
'c-btn--loading': this.isPost,
'u-c-cyan': this.isPost,
'c-btn--disabled': this.isEmpty
}
]
}
},
methods: {
cancel () {
Tips.confirm('确认取消?').then(() => {
wx.navigateBack({
delta: 2
})
}).catch(() => {
console.log('取消')
})
// this.$showDialog({
// content: '确定取消?',
// showCancel: true
// }).then(async () => {
// wx.navigateBack({
// delta: 2
// })
// }).catch(() => {
// this.dialog.show = false
// })
},
async formSubmit (e) {
// console.log(this.postId)
// if (!this.postId) {
// return
// }
this.isPost = true
const commentData = {
// formId: e.target.formId,
content: this.content,
postId: this.postId,
meta: {
style: JSON.stringify(this.selectedColor)
}
}
// console.log(commentData)
// console.log(commentData)
const res = await postsApi.repliesNew(this.postId, commentData)
// console.log(res)
if (res) {
await Tips.success('成功发表评论')
}
Route.backOrRedirect(`/pages/detail?id=${this.postId}&#comments`)
},
changeColor () {
// this.isSliderDisplay = !this.isSliderDisplay
// this.isFocus = false
// this.bindBlur()
if (this.autoFocus === true) {
this.autoFocus = false
this.isSliderDisplay = true
return true
}
this.isSliderDisplay = !this.isSliderDisplay
},
handleSelectdColor (item) {
this.selectedColor = item
},
_wordCount (data) {
const pattern = /[a-zA-Z0-9_\u0392-\u03c9\u0410-\u04F9]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/g
const m = data.match(pattern)
let count = 0
if (m === null) {
return count
}
for (let i = 0; i < m.length; i++) {
if (m[i].charCodeAt(0) >= 0x4E00) {
count += m[i].length
} else {
count += 1
}
}
return count
},
bindInput (e) {
this.content = e.target.value
},
bindFocus () {
this.autoFocus = true
},
bindBlur () {
this.autoFocus = false
}
},
async onLoad () {
const query = this.$root.$mp.query
this.postId = query.postId
wx.setNavigationBarTitle({title: `评价「${query.title}」`})
}
}
</script>
??
如果本项目对您有帮助,欢迎 “点赞,关注” 支持一下 谢谢~
源码获取关注公众号「码农园区」,回复 【源码】