feat: first commit
|
|
@ -0,0 +1,20 @@
|
||||||
|
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
|
||||||
|
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
|
||||||
|
"version": "0.0",
|
||||||
|
"configurations": [{
|
||||||
|
"app-plus" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
|
"default" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
|
"mp-weixin" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
|
"type" : "uniCloud"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['token'])
|
||||||
|
},
|
||||||
|
onLaunch: function() {
|
||||||
|
console.log('App Launch')
|
||||||
|
if (this.token) {
|
||||||
|
this.getUserInfo()
|
||||||
|
} else {
|
||||||
|
// #ifdef H5
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
console.log('App Show')
|
||||||
|
uni.hideTabBar()
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
console.log('App Hide')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
...mapActions(['getUserInfo']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!--
|
||||||
|
待完成:
|
||||||
|
1. 短剧列表 -
|
||||||
|
3. 邀请好友收入 -
|
||||||
|
4. 数据收益 -
|
||||||
|
5. 任务详情
|
||||||
|
6. 我的钱包,收益提现等
|
||||||
|
7. 我的-账号管理
|
||||||
|
8. 我的-邀请好友 -
|
||||||
|
9. 消息 -
|
||||||
|
|
||||||
|
1. 推广操作,我的推广链接
|
||||||
|
2. 小程序首页的变现项目里的我要加入,是个什么操作,麻雀的是跳转app下载链接页
|
||||||
|
3. 邀请好友操作
|
||||||
|
4. 提现操作
|
||||||
|
5. 账号管理新建账号
|
||||||
|
|
||||||
|
任务接口:
|
||||||
|
1. 少了图片字段
|
||||||
|
2. 视频数、播放数、评论数、获赞数。这个不知道先需要做成什么样需要问问
|
||||||
|
3. 详情里的播放排行也需要确定下
|
||||||
|
-->
|
||||||
|
<style lang="scss">
|
||||||
|
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
|
||||||
|
@import "@/uni_modules/uview-ui/index.scss";
|
||||||
|
|
||||||
|
page {
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-text {
|
||||||
|
color: $uni-theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-menu {
|
||||||
|
border-radius: 10upx;
|
||||||
|
margin-top: 20upx;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .c-menu .u-form-item:last-child {
|
||||||
|
.u-line {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .c-menu .u-cell:last-child {
|
||||||
|
.u-line {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-btn:active {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.wrap {
|
||||||
|
background-color: #F7F8FA;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-start {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-end {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-start {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-end {
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-nowrap {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-20 {
|
||||||
|
padding: 20upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-30 {
|
||||||
|
padding: 30upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-d-20 {
|
||||||
|
padding: 20upx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-r-20 {
|
||||||
|
padding: 0 20upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded {
|
||||||
|
border-radius: 20upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
import {
|
||||||
|
toast,
|
||||||
|
loading
|
||||||
|
} from "@/utils/common"
|
||||||
|
|
||||||
|
let url;
|
||||||
|
// #ifdef H5
|
||||||
|
url = '/api'
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
url = 'http://www.opsoul.com'
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
export const uri = url;
|
||||||
|
|
||||||
|
const axios = {
|
||||||
|
header() {
|
||||||
|
return {
|
||||||
|
// 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
|
||||||
|
// 'Cookie': uni.getStorageSync('token') ? `${uni.getStorageSync('token')}` : ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success(res) {
|
||||||
|
if (res.data.code != "100000" && res.data.msg) {
|
||||||
|
toast(res.data.msg);
|
||||||
|
err(res.data.code);
|
||||||
|
return res.data;
|
||||||
|
} else {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail() {
|
||||||
|
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
},
|
||||||
|
|
||||||
|
upload(url, data, showLoading = true) {
|
||||||
|
if (showLoading) loading();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: uri + '/common/upload',
|
||||||
|
name: 'file',
|
||||||
|
file: data,
|
||||||
|
header: axios.header(),
|
||||||
|
success: res => {
|
||||||
|
resolve(axios.success(res));
|
||||||
|
},
|
||||||
|
fail: axios.fail,
|
||||||
|
complete: axios.complete
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
post(url, data, showLoading = true, contentType = 'application/json;charset=utf-8') {
|
||||||
|
if (showLoading) loading();
|
||||||
|
console.log(data);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: uri + url,
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
header: {
|
||||||
|
// ...axios.header(),
|
||||||
|
'Content-Type': contentType
|
||||||
|
},
|
||||||
|
success: res => {
|
||||||
|
resolve(axios.success(res));
|
||||||
|
},
|
||||||
|
fail: axios.fail,
|
||||||
|
complete: axios.complete
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
put(url, data, showLoading = true) {
|
||||||
|
console.log(url);
|
||||||
|
if (showLoading) loading();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: uri + url,
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
header: axios.header(),
|
||||||
|
success: res => {
|
||||||
|
resolve(axios.success(res));
|
||||||
|
},
|
||||||
|
fail: axios.fail,
|
||||||
|
complete: axios.complete
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
delete(url, data, showLoading = true) {
|
||||||
|
console.log(url);
|
||||||
|
if (showLoading) loading();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: uri + url,
|
||||||
|
method: 'delete',
|
||||||
|
data: data,
|
||||||
|
header: axios.header(),
|
||||||
|
success: res => {
|
||||||
|
resolve(axios.success(res));
|
||||||
|
},
|
||||||
|
fail: axios.fail,
|
||||||
|
complete: axios.complete
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
get(url, data) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.request({
|
||||||
|
url: uri + url,
|
||||||
|
method: 'get',
|
||||||
|
data: data,
|
||||||
|
header: axios.header(),
|
||||||
|
success: res => {
|
||||||
|
resolve(axios.success(res));
|
||||||
|
},
|
||||||
|
fail: (e) => {
|
||||||
|
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function err(code) {
|
||||||
|
if (code == 401) {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default axios;
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
import axios, {uri} from "./api.config.js"
|
||||||
|
|
||||||
|
export const baseUrl = uri
|
||||||
|
export const baseImgUrl = uri + '/admin'
|
||||||
|
|
||||||
|
export const codeGetOpenID = data => axios.post('/tool/wx/getOpenidByCode',data, true, 'application/x-www-form-urlencoded;charset=utf-8')
|
||||||
|
|
||||||
|
export const loginByOpenid = data => axios.post('/app/user/loginByOpenid',data, true, 'application/x-www-form-urlencoded;charset=utf-8')
|
||||||
|
|
||||||
|
export const sendSmsCode = data => axios.post('/tool/sms/sendSmsCode',data, true, 'application/x-www-form-urlencoded;charset=utf-8')
|
||||||
|
|
||||||
|
export const loginByPassword = data => axios.post('/app/user/loginByPassword',data)
|
||||||
|
|
||||||
|
export const updateUserById = data => axios.post('/app/user/updatePlayletUser',data)
|
||||||
|
|
||||||
|
export const updatePasswordByCode = data => axios.post('/app/user/updatePasswordByCode',data)
|
||||||
|
|
||||||
|
export const getBannerList = data => axios.post('/app/banner/getBannerList',data)
|
||||||
|
|
||||||
|
export const getMessageList = data => axios.post('/app/message/getMessageList',data)
|
||||||
|
|
||||||
|
export const getMessagePage = (pageNum, pageSize, data) => axios.post(`/app/message/getMessagePage?pageNum=${pageNum}&pageSize=${pageSize}`,data)
|
||||||
|
|
||||||
|
export const getCustomerList = data => axios.post('/app/customer/getCustomerList',data)
|
||||||
|
|
||||||
|
export const getProjectList = data => axios.post('/app/project/getProjectList',data)
|
||||||
|
// 短剧视频接口
|
||||||
|
export const getItemList = (pageNum, pageSize, data) => axios.post(`/app/item/getItemList?pageNum=${pageNum}&pageSize=${pageSize}`,data)
|
||||||
|
// 获取剧场类型
|
||||||
|
export const getTypeList = data => axios.post('/app/type/getTypeList',data)
|
||||||
|
|
||||||
|
|
||||||
|
export const record = {
|
||||||
|
// 收益统计
|
||||||
|
statistics: data => axios.post('/app/record/statistics',data),
|
||||||
|
// 收益时间统计
|
||||||
|
statisticsTime: data => axios.post('/app/record/statistics/time',data),
|
||||||
|
// 收益统计时间分类
|
||||||
|
statisticsTimeType: data => axios.post('/app/record/statistics/time/type',data),
|
||||||
|
|
||||||
|
getRecordList: (pageNum, pageSize, data) => axios.post(`/app/record/getRecordList?pageNum=${pageNum}&pageSize=${pageSize}`,data)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const feedbackAdd = data => axios.post('/app/feedback/add',data)
|
||||||
|
|
||||||
|
export const feedbackList = (pageNum, pageSize, data) => axios.post(`/app/feedback/getFeedBackList?pageNum=${pageNum}&pageSize=${pageSize}`,data)
|
||||||
|
|
||||||
|
|
||||||
|
export const getTaskList = (pageNum, pageSize, data) => axios.post(`/app/task/getTaskList?pageNum=${pageNum}&pageSize=${pageSize}`,data)
|
||||||
|
|
||||||
|
// 提现账号管理
|
||||||
|
export const withdraw = {
|
||||||
|
getInfo: data => axios.post('/app/account/list',data, true, 'application/x-www-form-urlencoded;charset=utf-8'),
|
||||||
|
addAccount: data => axios.post('/app/account/add',data),
|
||||||
|
editAccount: data => axios.post('/app/account/edit',data),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const codeIvSignRegister = data => axios.post('/account/login', data)
|
||||||
|
|
||||||
|
export const getUserInfo = data => axios.post('/account/getAccount', data)
|
||||||
|
|
||||||
|
export const updateUserInfo = data => axios.post('/account/updateById', data)
|
||||||
|
|
||||||
|
export const storeList = _ => axios.post('/dept/list')
|
||||||
|
|
||||||
|
export const getMainData = data => axios.post('/main/getMainresource', data)
|
||||||
|
|
||||||
|
export const getPayList = data => axios.post('/setmenu/list', data)
|
||||||
|
|
||||||
|
export const saveCoin = data => axios.post('/currencyRecord/saveCurry', data)
|
||||||
|
|
||||||
|
export const getCoin = data => axios.post('/currencyRecord/withdraw', data)
|
||||||
|
|
||||||
|
export const coinRecord = data => axios.post('/account/currencyRecord', data)
|
||||||
|
|
||||||
|
export const saveIntegral = data => axios.post('/integralRecord/saveIntegral', data)
|
||||||
|
|
||||||
|
export const integralRecord = data => axios.post('/integralRecord/page', data)
|
||||||
|
|
||||||
|
export const productList = data => axios.post('/product/page', data)
|
||||||
|
|
||||||
|
export const productInfo = data => axios.post('/product/getById', data)
|
||||||
|
|
||||||
|
export const productCollet = data => axios.post('/product/collect', data)
|
||||||
|
|
||||||
|
export const productUnCollect = data => axios.post('/account/delCollect', data)
|
||||||
|
|
||||||
|
export const productApply = data => axios.post('/product/apply', data)
|
||||||
|
|
||||||
|
export const collectList = data => axios.post('/account/myCollect', data)
|
||||||
|
|
||||||
|
export const exchangeRecord = data => axios.post('/productRecord/page', data)
|
||||||
|
|
||||||
|
export const getDict = dictType => axios.get(`/dict/data/type/${dictType}`)
|
||||||
|
|
||||||
|
export const getStatistics = data => axios.post('/integralRecord/statistics', data)
|
||||||
|
|
||||||
|
export const payMoney = data => axios.post('/setmenu/pay', data)
|
||||||
|
|
||||||
|
export const suggestionAdd = data => axios.post('/suggestion/add', data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// export const login = {
|
||||||
|
// // 查房登录
|
||||||
|
// type1: data => axios.post('/bam/login',data),
|
||||||
|
// type2: data => axios.post('/clean/login',data),
|
||||||
|
// type3: data => axios.post('/project/login',data)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export const userInfo = {
|
||||||
|
// info1: _ => axios.get('/bam/admin/getByToken'),
|
||||||
|
// info2: _ => axios.get('/clean/staff/getByToken'),
|
||||||
|
// info3: _ => axios.get('/project/staff/getByToken'),
|
||||||
|
// // 保洁--根据token查询本人房间分组
|
||||||
|
// cleanInfoData: _ => axios.get('/clean/staff/getByGroup'),
|
||||||
|
// // 获取平均保洁时长
|
||||||
|
// getAvgClean: _ => axios.get('/clean/staff/getAvgClean'),
|
||||||
|
// // 修改上下班状态/clean/staff/offWork
|
||||||
|
// offWork: workStatus => axios.put('/clean/staff/offWork?workStatus='+workStatus),
|
||||||
|
// // 工程端本月累计完成工单和获取维修人员本月平均维修时长(返回毫秒值)
|
||||||
|
// getAvgProject: _ => axios.get('/project/staff/getAvgProject'),
|
||||||
|
// // 今日分房
|
||||||
|
// getTodayDispathRoom: _ => axios.get('/clean/staff/getByRoomDistribute')
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 更改密码
|
||||||
|
// export const changePwd = {
|
||||||
|
// c1: data => axios.put(`/bam/admin/updatePw?oldPw=${data.oldPw}&pw=${data.pw}&rePw=${data.rePw}`,data),
|
||||||
|
// c2: data => axios.put(`/clean/staff/updatePw?oldPw=${data.oldPw}&pw=${data.pw}&rePw=${data.rePw}`,data),
|
||||||
|
// c3: data => axios.put(`/project/staff/updatePw?oldPw=${data.oldPw}&pw=${data.pw}&rePw=${data.rePw}`,data)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export const notice = {
|
||||||
|
// list: data => axios.get('/clean/notice/page', data),
|
||||||
|
// info: id => axios.get(`/clean/notice/${id}`),
|
||||||
|
// projectList: data => axios.get('/project/notice/page', data),
|
||||||
|
// projectInfo: id => axios.get(`/project/notice/${id}`),
|
||||||
|
// adminList: data => axios.get('/bam/index/pageIndexNotice', data),
|
||||||
|
// adminInfo: id => axios.get(`/bam/notice/getItem/${id}`),
|
||||||
|
// // 满房提醒
|
||||||
|
// roomalarm: data => axios.get('/jy/roomalarm/list/page', data),
|
||||||
|
// roomalarmRead: id => axios.post('/jy/roomalarm/read/'+id, {}),
|
||||||
|
// // 新增公告
|
||||||
|
// addHotelNotice: (hotelId, data) => axios.post('/bam/notice/addHotelNotice?hotelId='+hotelId, data),
|
||||||
|
// // 发布公告
|
||||||
|
// pushHotelNotice: (hotelId, id) => axios.put('/bam/notice/pushHotelNotice?hotelId='+hotelId+'&id='+id),
|
||||||
|
// // 获取公告标签列表
|
||||||
|
// getLabelList: hotelId => axios.get('/bam/label-manager/list?hotelId='+hotelId+'&type=2'),
|
||||||
|
// // 获取人员标签
|
||||||
|
// getMemberLabelList: hotelId => axios.get('/bam/label-manager/list?hotelId='+hotelId+'&type=1'),
|
||||||
|
// }
|
||||||
|
|
@ -0,0 +1,558 @@
|
||||||
|
<template>
|
||||||
|
<view class="cmd-progress cmd-progress-default" :class="setStatusClass">
|
||||||
|
<block v-if="type == 'circle' || type == 'dashboard'">
|
||||||
|
<view class="cmd-progress cmd-progress-default" :class="setStatusClass">
|
||||||
|
<view class="cmd-progress-inner" :style="setCircleStyle">
|
||||||
|
<!-- 绘制圈 start -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<svg viewBox="0 0 100 100" class="cmd-progress-circle">
|
||||||
|
<path :d="setCirclePath" stroke="#f3f3f3" :stroke-linecap="strokeShape" :stroke-width="strokeWidth"
|
||||||
|
fill-opacity="0" class="cmd-progress-circle-trail" :style="setCircleTrailStyle"></path>
|
||||||
|
<path :d="setCirclePath" :stroke-linecap="strokeShape" :stroke-width="strokeWidth" fill-opacity="0" class="cmd-progress-circle-path"
|
||||||
|
:style="setCirclePathStyle"></path>
|
||||||
|
</svg>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<text :style="setCircle"></text>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- 绘制圈 end -->
|
||||||
|
<!-- 状态文本 start -->
|
||||||
|
<block v-if="showInfo">
|
||||||
|
<text class="cmd-progress-text" :title="setFormat">
|
||||||
|
<block v-if="status != 'success' && status != 'exception' && setProgress < 100">{{setFormat}}</block>
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<svg v-if="status == 'exception'" viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor"
|
||||||
|
aria-hidden="true">
|
||||||
|
<path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
|
||||||
|
</svg>
|
||||||
|
<svg v-if="status == 'success' || setProgress == 100" viewBox="64 64 896 896" data-icon="check" width="1em"
|
||||||
|
height="1em" fill="currentColor" aria-hidden="true" :style="{'color': strokeColor ? strokeColor : ''}">
|
||||||
|
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path>
|
||||||
|
</svg>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<text v-if="status == 'exception' || status == 'success' || setProgress == 100" :style="setCircleIcon"></text>
|
||||||
|
<!-- #endif -->
|
||||||
|
</text>
|
||||||
|
</block>
|
||||||
|
<!-- 状态文本 end -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<block v-if="type == 'line'">
|
||||||
|
<!-- 进度条 start -->
|
||||||
|
<view class="cmd-progress-outer">
|
||||||
|
<view class="cmd-progress-inner" :style="{'border-radius': strokeShape == 'square' ? 0 : '100px'}">
|
||||||
|
<view class="cmd-progress-bg" :style="setLineStyle"></view>
|
||||||
|
<view v-if="successPercent" class="cmd-progress-success-bg" :style="setLineSuccessStyle"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 进度条 end -->
|
||||||
|
<!-- 进度条是否显示信息 start -->
|
||||||
|
<block v-if="showInfo">
|
||||||
|
<text class="cmd-progress-text" :title="setFormat">
|
||||||
|
<block v-if="status != 'success' && status != 'exception' && setProgress < 100">{{setFormat}}</block>
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<svg v-if="status == 'exception'" viewBox="64 64 896 896" data-icon="close-circle" width="1em" height="1em"
|
||||||
|
fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path>
|
||||||
|
</svg>
|
||||||
|
<svg v-if="status == 'success' || setProgress == 100" viewBox="64 64 896 896" data-icon="check-circle" width="1em"
|
||||||
|
height="1em" fill="currentColor" aria-hidden="true" :style="{'color': strokeColor ? strokeColor : ''}">
|
||||||
|
<path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 0 1-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path>
|
||||||
|
</svg>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<text v-if="status == 'exception' || status == 'success' || setProgress == 100" :style="setLineStatusIcon"></text>
|
||||||
|
<!-- #endif -->
|
||||||
|
</text>
|
||||||
|
</block>
|
||||||
|
<!-- 进度条是否显示信息 end -->
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 进度条组件
|
||||||
|
* @description 显示一个操作完成的百分比时,为用户显示该操作的当前进度和状态。
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=259
|
||||||
|
* @property {String} type 进度类型 - 线型:line、圆圈形:circle、仪表盘:dashboard,默认线型:line
|
||||||
|
* @property {Number} percent 进度百分比值 - 显示范围0-100 ,可能数比较大就需要自己转成百分比的值
|
||||||
|
* @property {Number} success-percent 进度已完成的百分几 - 仅支持进度线型:line
|
||||||
|
* @property {String} status 进度状态 - 涌动:active(仅支持线型:line)、正常:normal、完成:success、失败:exception,默认正常:normal
|
||||||
|
* @property {Boolean} show-info 进度状态信息 - 是否显示进度数值或状态图标,默认true
|
||||||
|
* @property {Number} stroke-width 进度线条的宽度 - 建议在条线的宽度范围:1-50,与进度条显示宽度有关,默认8
|
||||||
|
* @property {String} stroke-color 进度线条的颜色 - 渐变色仅支持线型:line
|
||||||
|
* @property {String} stroke-shape 进度线条两端的形状 - 圆:round、方块直角:square,默认圆:round
|
||||||
|
* @property {Number} width 进度画布宽度 - 仅支持圆圈形:circle、仪表盘:dashboard,默认80
|
||||||
|
* @property {String} gap-degree 进度圆形缺口角度 - 可取值 0 ~ 360,仅支持圆圈形:circle、仪表盘:dashboard
|
||||||
|
* @property {String} gap-position 进度圆形缺口位置 - 可取值'top', 'bottom', 'left', 'right',仅支持圆圈形:circle、仪表盘:dashboard
|
||||||
|
* @example <cmd-progress :percent="30"></cmd-progress>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'cmd-progress',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 类型默认:line,可选 line circle dashboard
|
||||||
|
*/
|
||||||
|
type: {
|
||||||
|
validator: val => {
|
||||||
|
return ['line', 'circle', 'dashboard'].includes(val);
|
||||||
|
},
|
||||||
|
default: 'line'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 百分比
|
||||||
|
*/
|
||||||
|
percent: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 已完成的分段百分,仅支持类型line
|
||||||
|
*/
|
||||||
|
successPercent: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否显示进度数值或状态图标
|
||||||
|
*/
|
||||||
|
showInfo: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度状态,可选:normal success exception (active仅支持类型line
|
||||||
|
*/
|
||||||
|
status: {
|
||||||
|
validator: val => {
|
||||||
|
return ['normal', 'success', 'exception', 'active'].includes(val);
|
||||||
|
},
|
||||||
|
default: 'normal'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 条线的宽度1-50,与width有关
|
||||||
|
*/
|
||||||
|
strokeWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 6
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 条线的颜色,渐变色仅支持类型line
|
||||||
|
*/
|
||||||
|
strokeColor: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 条线两端的形状 可选:'round', 'square'
|
||||||
|
*/
|
||||||
|
strokeShape: {
|
||||||
|
validator: val => {
|
||||||
|
return ['round', 'square'].includes(val);
|
||||||
|
},
|
||||||
|
default: 'round'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 圆形进度条画布宽度,支持类型circle dashboard
|
||||||
|
*/
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 80
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 圆形进度条缺口角度,可取值 0 ~ 360,支持类型circle dashboard
|
||||||
|
*/
|
||||||
|
gapDegree: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 圆形进度条缺口位置,可取值'top', 'bottom', 'left', 'right' ,支持类型circle dashboard
|
||||||
|
*/
|
||||||
|
gapPosition: {
|
||||||
|
validator: val => {
|
||||||
|
return ['top', 'bottom', 'left', 'right'].includes(val);
|
||||||
|
},
|
||||||
|
default: 'top'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* 如果需要自定义格式就在这改
|
||||||
|
*/
|
||||||
|
setFormat() {
|
||||||
|
return `${this.setProgress}%`;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 设置显示进度值,禁止小于0和超过100
|
||||||
|
*/
|
||||||
|
setProgress() {
|
||||||
|
let percent = this.percent;
|
||||||
|
if (!this.percent || this.percent < 0) {
|
||||||
|
percent = 0;
|
||||||
|
} else if (this.percent >= 100) {
|
||||||
|
percent = 100;
|
||||||
|
}
|
||||||
|
return percent;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 进度圈svg大小
|
||||||
|
*/
|
||||||
|
setCircleStyle() {
|
||||||
|
return `width: ${this.width}px;
|
||||||
|
height: ${this.width}px;
|
||||||
|
fontSize: ${this.width * 0.15 + 6}px;`
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 圈底色
|
||||||
|
*/
|
||||||
|
setCircleTrailStyle() {
|
||||||
|
const radius = 50 - this.strokeWidth / 2;
|
||||||
|
const len = Math.PI * 2 * radius;
|
||||||
|
const gapDeg = this.gapDegree || (this.type === 'dashboard' && 75);
|
||||||
|
return `stroke-dasharray: ${len - (gapDeg||0)}px, ${len}px;
|
||||||
|
stroke-dashoffset: -${(gapDeg||0) / 2}px;
|
||||||
|
transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s;`
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 圈进度
|
||||||
|
*/
|
||||||
|
setCirclePathStyle() {
|
||||||
|
const radius = 50 - this.strokeWidth / 2;
|
||||||
|
const len = Math.PI * 2 * radius;
|
||||||
|
const gapDeg = this.gapDegree || (this.type === 'dashboard' && 75);
|
||||||
|
return `stroke: ${this.strokeColor};
|
||||||
|
stroke-dasharray: ${(this.setProgress / 100) * (len - (gapDeg||0))}px, ${len}px;
|
||||||
|
stroke-dashoffset: -${(gapDeg||0) / 2}px;
|
||||||
|
transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s, stroke-width 0.06s ease 0.3s;`
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 绘制圈
|
||||||
|
*/
|
||||||
|
setCirclePath() {
|
||||||
|
const radius = 50 - this.strokeWidth / 2;
|
||||||
|
let beginPositionX = 0;
|
||||||
|
let beginPositionY = -radius;
|
||||||
|
let endPositionX = 0;
|
||||||
|
let endPositionY = -2 * radius;
|
||||||
|
const gapPos = (this.type === 'dashboard' && 'bottom') || this.gapPosition || 'top';
|
||||||
|
switch (gapPos) {
|
||||||
|
case 'left':
|
||||||
|
beginPositionX = -radius;
|
||||||
|
beginPositionY = 0;
|
||||||
|
endPositionX = 2 * radius;
|
||||||
|
endPositionY = 0;
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
beginPositionX = radius;
|
||||||
|
beginPositionY = 0;
|
||||||
|
endPositionX = -2 * radius;
|
||||||
|
endPositionY = 0;
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
beginPositionY = radius;
|
||||||
|
endPositionY = 2 * radius;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return `M 50,50 m ${beginPositionX},${beginPositionY} a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY} a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
|
||||||
|
},
|
||||||
|
// #ifndef H5
|
||||||
|
/**
|
||||||
|
* 非H5端,绘制进度圈svg转base URL
|
||||||
|
*/
|
||||||
|
setCircle() {
|
||||||
|
const radius = 50 - this.strokeWidth / 2;
|
||||||
|
const len = Math.PI * 2 * radius;
|
||||||
|
const gapDeg = this.gapDegree || (this.type === 'dashboard' && 75);
|
||||||
|
let currentColor = '#108ee9'
|
||||||
|
// 异常进度
|
||||||
|
if (this.status == 'exception') {
|
||||||
|
currentColor = '#f5222d'
|
||||||
|
}
|
||||||
|
// 完成进度
|
||||||
|
if (this.status == 'success' || this.setProgress >= 100 || this.strokeColor) {
|
||||||
|
currentColor = this.strokeColor || '#52c41a'
|
||||||
|
}
|
||||||
|
let svgToBase =
|
||||||
|
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' class='cmd-progress-circle'%3E%3Cpath d='${this.setCirclePath}' stroke='%23f3f3f3' stroke-linecap='${this.strokeShape}' stroke-width='${this.strokeWidth}' fill-opacity='0' class='cmd-progress-circle-trail' style='stroke-dasharray: ${len - (gapDeg||0)}px, ${len}px;stroke-dashoffset: -${(gapDeg||0) / 2}px;transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s;'%3E%3C/path%3E%3Cpath d='${this.setCirclePath}' stroke-linecap='${this.strokeShape}' stroke-width='${this.strokeWidth}' fill-opacity='0' class='cmd-progress-circle-path' style='stroke: ${escape(currentColor)};stroke-dasharray: ${(this.setProgress / 100) * (len - (gapDeg||0))}px, ${len}px;stroke-dashoffset: -${(gapDeg||0) / 2}px;transition: stroke-dashoffset 0.3s ease 0s, stroke-dasharray 0.3s ease 0s, stroke 0.3s, stroke-width 0.06s ease 0.3s;'%3E%3C/path%3E%3C/svg%3E`
|
||||||
|
return `background-image: url("${svgToBase}");
|
||||||
|
background-size: cover;
|
||||||
|
display: inline-block;
|
||||||
|
${this.setCircleStyle}`;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 设置进度圈状态图标
|
||||||
|
*/
|
||||||
|
setCircleIcon() {
|
||||||
|
let currentColor = '#108ee9'
|
||||||
|
let svgToBase = ''
|
||||||
|
// 异常进度
|
||||||
|
if (this.status == 'exception') {
|
||||||
|
currentColor = '#f5222d'
|
||||||
|
svgToBase =
|
||||||
|
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='close' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z'%3E%3C/path%3E %3C/svg%3E`;
|
||||||
|
}
|
||||||
|
// 完成进度
|
||||||
|
if (this.status == 'success' || this.setProgress >= 100) {
|
||||||
|
currentColor = this.strokeColor || '#52c41a'
|
||||||
|
svgToBase =
|
||||||
|
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='check' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z'%3E%3C/path%3E %3C/svg%3E`;
|
||||||
|
}
|
||||||
|
return `background-image: url("${svgToBase}");
|
||||||
|
background-size: cover;
|
||||||
|
display: inline-block;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;`;
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
/**
|
||||||
|
* 设置进度条样式
|
||||||
|
*/
|
||||||
|
setLineStyle() {
|
||||||
|
return `width: ${this.setProgress}%;
|
||||||
|
height: ${this.strokeWidth}px;
|
||||||
|
background: ${this.strokeColor};
|
||||||
|
border-radius: ${this.strokeShape === 'square' ? 0 : '100px'};`;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 设置已完成分段进度
|
||||||
|
*/
|
||||||
|
setLineSuccessStyle() {
|
||||||
|
let successPercent = this.successPercent;
|
||||||
|
if (!this.successPercent || this.successPercent < 0 || this.setProgress < this.successPercent) {
|
||||||
|
successPercent = 0;
|
||||||
|
} else if (this.successPercent >= 100) {
|
||||||
|
successPercent = 100;
|
||||||
|
}
|
||||||
|
return `width: ${successPercent}%;
|
||||||
|
height: ${this.strokeWidth}px;
|
||||||
|
border-radius: ${this.strokeShape === 'square' ? 0 : '100px'};`;
|
||||||
|
},
|
||||||
|
// #ifndef H5
|
||||||
|
/**
|
||||||
|
* 设置进度条状态图标
|
||||||
|
*/
|
||||||
|
setLineStatusIcon() {
|
||||||
|
let currentColor = '#108ee9'
|
||||||
|
let svgToBase = ''
|
||||||
|
// 异常进度
|
||||||
|
if (this.status == 'exception') {
|
||||||
|
currentColor = '#f5222d'
|
||||||
|
svgToBase =
|
||||||
|
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='close-circle' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z'%3E%3C/path%3E %3C/svg%3E`;
|
||||||
|
}
|
||||||
|
// 完成进度
|
||||||
|
if (this.status == 'success' || this.setProgress >= 100) {
|
||||||
|
currentColor = this.strokeColor || '#52c41a'
|
||||||
|
svgToBase =
|
||||||
|
`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896' data-icon='check-circle' width='1em' height='1em' fill='${escape(currentColor)}' aria-hidden='true'%3E %3Cpath d='M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 0 1-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z'%3E%3C/path%3E %3C/svg%3E`;
|
||||||
|
}
|
||||||
|
return `background-image: url("${svgToBase}");
|
||||||
|
background-size: cover;
|
||||||
|
display: inline-block;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;`;
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
/**
|
||||||
|
* 状态样式
|
||||||
|
*/
|
||||||
|
setStatusClass() {
|
||||||
|
let statusClass = [];
|
||||||
|
// 异常进度
|
||||||
|
if (this.status == 'exception') {
|
||||||
|
statusClass.push('cmd-progress-status-exception')
|
||||||
|
}
|
||||||
|
// 完成进度
|
||||||
|
if (this.status == 'success' || this.setProgress >= 100) {
|
||||||
|
statusClass.push('cmd-progress-status-success')
|
||||||
|
}
|
||||||
|
// 活动进度条
|
||||||
|
if (this.status == 'active') {
|
||||||
|
statusClass.push('cmd-progress-status-active')
|
||||||
|
}
|
||||||
|
// 是否显示信息
|
||||||
|
if (this.showInfo) {
|
||||||
|
statusClass.push('cmd-progress-show-info')
|
||||||
|
}
|
||||||
|
// 进度条类型
|
||||||
|
if (this.type === 'line') {
|
||||||
|
statusClass.push('cmd-progress-line')
|
||||||
|
}
|
||||||
|
// 进度圈、仪表盘类型
|
||||||
|
if (this.type === 'circle' || this.type === 'dashboard') {
|
||||||
|
statusClass.push('cmd-progress-circle')
|
||||||
|
}
|
||||||
|
statusClass.push('cmd-progress-status-normal')
|
||||||
|
return statusClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.cmd-progress {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-line {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 28upx;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-outer {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
margin-right: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-show-info .cmd-progress-outer {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-inner {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 200upx;
|
||||||
|
vertical-align: middle;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-circle-trail {
|
||||||
|
stroke: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-circle-path {
|
||||||
|
stroke: #1890ff;
|
||||||
|
animation: appear 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-success-bg,
|
||||||
|
.cmd-progress-bg {
|
||||||
|
background-color: #1890ff;
|
||||||
|
transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-success-bg {
|
||||||
|
background-color: #52c41a;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-text {
|
||||||
|
word-break: normal;
|
||||||
|
width: 60upx;
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 16upx;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-active .cmd-progress-bg:before {
|
||||||
|
content: "";
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
-webkit-animation: cmd-progress-active 2.4s cubic-bezier(0.23, 1, 0.32, 1) infinite;
|
||||||
|
animation: cmd-progress-active 2.4s cubic-bezier(0.23, 1, 0.32, 1) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-exception .cmd-progress-bg {
|
||||||
|
background-color: #f5222d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-exception .cmd-progress-text {
|
||||||
|
color: #f5222d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-exception .cmd-progress-circle-path {
|
||||||
|
stroke: #f5222d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-success .cmd-progress-bg {
|
||||||
|
background-color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-success .cmd-progress-text {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-status-success .cmd-progress-circle-path {
|
||||||
|
stroke: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-circle .cmd-progress-inner {
|
||||||
|
position: relative;
|
||||||
|
line-height: 1;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-circle .cmd-progress-text {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1;
|
||||||
|
top: 50%;
|
||||||
|
-webkit-transform: translateY(-50%);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
left: 0;
|
||||||
|
margin: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-circle .cmd-progress-status-exception .cmd-progress-text {
|
||||||
|
color: #f5222d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmd-progress-circle .cmd-progress-status-success .cmd-progress-text {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cmd-progress-active {
|
||||||
|
0% {
|
||||||
|
opacity: 0.1;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
opacity: 0.5;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
<template>
|
||||||
|
<view class="loading">
|
||||||
|
<view class="bg-white">
|
||||||
|
<slot>
|
||||||
|
<image v-if="gifSrc" :src="gifSrc" mode="aspectFit"></image>
|
||||||
|
<text>加载中</text>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
// gif地址
|
||||||
|
gifSrc: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loading {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
opacity: 0.99;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white image {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
display: block;
|
||||||
|
margin-top: -20px;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white text {
|
||||||
|
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="page-content">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<u-tabbar
|
||||||
|
:value="current"
|
||||||
|
:placeholder="true"
|
||||||
|
:safeAreaInsetBottom="true"
|
||||||
|
>
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<u-tabbar-item text="首页" icon="home" @click="changeTab(0)" ></u-tabbar-item>
|
||||||
|
<u-tabbar-item text="短剧" icon="photo" @click="changeTab(1)" ></u-tabbar-item>
|
||||||
|
<u-tabbar-item text="数据" icon="integral" @click="changeTab(2)" ></u-tabbar-item>
|
||||||
|
<u-tabbar-item text="任务" icon="play-right" @click="changeTab(3)" ></u-tabbar-item>
|
||||||
|
<u-tabbar-item text="我的" icon="account" @click="changeTab(4)" ></u-tabbar-item>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<u-tabbar-item text="首页" icon="home" @click="changeTab(0)" ></u-tabbar-item>
|
||||||
|
<u-tabbar-item text="变现" icon="photo" @click="changeTab(1)" ></u-tabbar-item>
|
||||||
|
<u-tabbar-item text="我的" icon="account" @click="changeTab(2)" ></u-tabbar-item>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
</u-tabbar>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
name:"gTabbar",
|
||||||
|
props: {
|
||||||
|
current: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['token'])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
uni.hideTabBar()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
uni.hideTabBar()
|
||||||
|
if(this.token) {
|
||||||
|
this.getUserInfo()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getUserInfo']),
|
||||||
|
changeTab(name) {
|
||||||
|
if(name == this.current) return;
|
||||||
|
let url = ''
|
||||||
|
// #ifdef H5
|
||||||
|
switch(name) {
|
||||||
|
case 0:
|
||||||
|
url = '/pages/home/h5/h5'
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
url = '/pages/shortPlay/shortPlay'
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
url = '/pages/my/h5/h5'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
switch(name) {
|
||||||
|
case 0:
|
||||||
|
url = '/pages/home/mini/mini'
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
url = '/pages/shortPlay/shortPlay'
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
url = '/pages/data/data'
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
url = '/pages/task/task'
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
url = '/pages/my/mini/mini'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if(this.token || (!this.token && ['/pages/home/mini/mini', '/pages/shortPlay/shortPlay'].includes(url))) {
|
||||||
|
uni.switchTab({
|
||||||
|
url,
|
||||||
|
success() {
|
||||||
|
uni.hideTabBar()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({
|
||||||
|
// #ifdef H5
|
||||||
|
url: '/pages/login/login',
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
url: '/pages/entry/entry'
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page-content {
|
||||||
|
width: 100vw;
|
||||||
|
background-color: #F7F8FA;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_style {
|
||||||
|
width: 132upx;
|
||||||
|
height: 132upx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 132upx;
|
||||||
|
height: 132upx;
|
||||||
|
margin-top: -36upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginBtn {
|
||||||
|
width: 686upx;
|
||||||
|
height: 88upx;
|
||||||
|
background: linear-gradient(180deg, #C8F8B4 0%, #53DC1A 100%);
|
||||||
|
font-size: 36upx;
|
||||||
|
font-family: Source Han Sans SC, Source Han Sans SC;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 44upx;
|
||||||
|
margin-top: 132upx;
|
||||||
|
margin-bottom: 44upx;
|
||||||
|
position: relative;
|
||||||
|
view {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disagreeBtn {
|
||||||
|
width: 686upx;
|
||||||
|
height: 88upx;
|
||||||
|
background: #EBEDF0;
|
||||||
|
font-size: 36upx;
|
||||||
|
font-family: Source Han Sans SC, Source Han Sans SC;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #323233;
|
||||||
|
border-radius: 44upx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 132upx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<u-modal :show="show" title="请添加客服微信" :closeOnClickOverlay="true" :showCancelButton="true"
|
||||||
|
:showConfirmButton="false" cancelText="关闭" cancelColor="#007aff" @cancel="closeHandle" @close="closeHandle">
|
||||||
|
<view class="flex flex-col justify-center items-center" style="width: 80%;">
|
||||||
|
<u-radio-group v-model="chooseCS" placement="column" @change="groupChange">
|
||||||
|
<u-radio :customStyle="{marginBottom: '8px'}" v-for="(item, index) in radiolist" :key="index"
|
||||||
|
:label="item.name" :name="index">
|
||||||
|
</u-radio>
|
||||||
|
</u-radio-group>
|
||||||
|
<image v-if="radiolist.length" style="width: 350upx;height: 350upx;"
|
||||||
|
:src="radiolist[chooseCS].url" mode="aspectFit"></image>
|
||||||
|
<view class="p-20">
|
||||||
|
<view style="color: #646566;font-size: 28upx;">添加请备注自己的用户ID</view>
|
||||||
|
<view style="color: #646566;font-size: 28upx;">截图本页去微信扫码添加</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-modal>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getCustomerList } from '@/api/index.js'
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
chooseCS: 0,
|
||||||
|
// 基本案列数据
|
||||||
|
radiolist: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getServiceList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getServiceList() {
|
||||||
|
const res = await getCustomerList({})
|
||||||
|
this.radiolist = res.data
|
||||||
|
this.chooseCS = 0
|
||||||
|
},
|
||||||
|
groupChange(n) {
|
||||||
|
this.chooseCS = n
|
||||||
|
},
|
||||||
|
closeHandle() {
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,483 @@
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<view style="padding: 0px 0px;">
|
||||||
|
<view class="filter-content" v-for="(item, index) in menuList" :key="index" v-if="menuIndex == index">
|
||||||
|
<view v-if="item.isSort">
|
||||||
|
<view class="filter-content-list">
|
||||||
|
<view v-for="(detailItem,idx) in selectDetailList" :key="idx" :class="detailItem.isSelected?'filter-content-list-item-active':'filter-content-list-item-default'"
|
||||||
|
:style="{'color': detailItem.isSelected?themeColor:'#666666'}" @tap="sortTap(idx,selectDetailList,item.key)">
|
||||||
|
<text>{{detailItem.title}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else>
|
||||||
|
<view class="filter-content-title" v-if="item.detailTitle && item.detailTitle.length">
|
||||||
|
<text>{{item.detailTitle}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="filter-content-detail">
|
||||||
|
<scroll-view scroll-y="true">
|
||||||
|
<view>
|
||||||
|
<text v-for="(detailItem,idx) in selectDetailList" :key="idx" class='filter-content-detail-item-default' :style="{'background-color':detailItem.isSelected?themeColor:'#FFFFFF','color':detailItem.isSelected?'#FFFFFF':'#666666'}"
|
||||||
|
@tap="itemTap(idx,selectDetailList,item.isMutiple,item.key)">
|
||||||
|
{{detailItem.title}}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<view class="filter-content-footer">
|
||||||
|
<view class="filter-content-footer-item" style="color: #777777; background-color: #FFFFFF;" @tap="resetClick(selectDetailList,item.key)">
|
||||||
|
<text>重置</text>
|
||||||
|
</view>
|
||||||
|
<view class="filter-content-footer-item" :style="{'color': '#FFFFFF', 'background-color': themeColor}" @tap="sureClick">
|
||||||
|
<text>确定</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectArr: [],
|
||||||
|
result: {},
|
||||||
|
menuIndex: 0,
|
||||||
|
selectDetailList: [],
|
||||||
|
independenceObj: {},
|
||||||
|
selectedKey: '',
|
||||||
|
cacheSelectedObj: {},
|
||||||
|
defaultSelectedTitleObj: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
themeColor: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '#D1372C'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
menuList: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
independence: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectedTitleObj() {
|
||||||
|
let obj = {}
|
||||||
|
for (let i = 0; i < this.menuList.length; i++) {
|
||||||
|
let item = this.menuList[i];
|
||||||
|
obj[item.key] = item.title;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
defaultSelectedObj() { // 保存初始状态
|
||||||
|
return this.getSelectedObj()
|
||||||
|
},
|
||||||
|
selectedObj: {
|
||||||
|
get() {
|
||||||
|
return this.getSelectedObj()
|
||||||
|
},
|
||||||
|
set(newObj) {
|
||||||
|
return newObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getSelectedObj() {
|
||||||
|
let obj = {}
|
||||||
|
for (let i = 0; i < this.menuList.length; i++) {
|
||||||
|
let item = this.menuList[i];
|
||||||
|
if (!this.independence && item.defaultSelectedIndex != null && item.defaultSelectedIndex.toString().length > 0) { // 处理并列菜单默认值
|
||||||
|
|
||||||
|
if (item.isMutiple) {
|
||||||
|
obj[item.key] = [];
|
||||||
|
item.detailList[0].isSelected = false;
|
||||||
|
if (!Array.isArray(item.defaultSelectedIndex)) { // 如果默认值不是数组
|
||||||
|
item.defaultSelectedIndex = [item.defaultSelectedIndex];
|
||||||
|
}
|
||||||
|
for (let j = 0; j < item.defaultSelectedIndex.length; j++) { // 将默认选中的值放入selectedObj
|
||||||
|
item.detailList[item.defaultSelectedIndex[j]].isSelected = true;
|
||||||
|
obj[item.key].push(item.detailList[item.defaultSelectedIndex[j]].value)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
obj[item.key] = item.detailList[item.defaultSelectedIndex].value;
|
||||||
|
this.selectedTitleObj[item.key] = item.detailList[item.defaultSelectedIndex].title;
|
||||||
|
this.defaultSelectedTitleObj[item.key] = item.detailList[item.defaultSelectedIndex].title;
|
||||||
|
item.detailList[0].isSelected = false;
|
||||||
|
item.detailList[item.defaultSelectedIndex].isSelected = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (item.isMutiple) {
|
||||||
|
obj[item.key] = [];
|
||||||
|
} else {
|
||||||
|
obj[item.key] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.result = obj;
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
// 重置所有选项,包括默认选项,并更新result
|
||||||
|
resetAllSelect(callback) {
|
||||||
|
let titles = [];
|
||||||
|
for (let i = 0; i < this.menuList.length; i++) {
|
||||||
|
this.resetSelected(this.menuList[i].detailList,this.menuList[i].key);
|
||||||
|
titles[this.menuList[i].key] = this.menuList[i].title;
|
||||||
|
}
|
||||||
|
let obj = {
|
||||||
|
'result': this.result,
|
||||||
|
'titles': titles,
|
||||||
|
'isReset': true
|
||||||
|
}
|
||||||
|
this.$emit("confirm", obj);
|
||||||
|
callback(this.result);
|
||||||
|
},
|
||||||
|
// 重置选项为设置的默认值,并更新result
|
||||||
|
resetSelectToDefault(callback) {
|
||||||
|
for (let i = 0; i < this.menuList.length; i++) {
|
||||||
|
this.selectDetailList = this.menuList[i].detailList;
|
||||||
|
|
||||||
|
if (this.menuList[i].defaultSelectedIndex) {
|
||||||
|
if (Array.isArray(this.menuList[i].defaultSelectedIndex)) { // 把所有默认的为false的点为true
|
||||||
|
for (let j = 0; j < this.menuList[i].defaultSelectedIndex.length; j++) {
|
||||||
|
if (this.selectDetailList[this.menuList[i].defaultSelectedIndex[j]].isSelected == false) {
|
||||||
|
this.itemTap(this.menuList[i].defaultSelectedIndex[j], this.selectDetailList, this.menuList[i].isMutiple, this
|
||||||
|
.menuList[i].key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.itemTap(this.menuList[i].defaultSelectedIndex, this.selectDetailList, this.menuList[i].isMutiple, this.menuList[
|
||||||
|
i].key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取非默认项的下标
|
||||||
|
let unDefaultSelectedIndexArr = this.getUnDefaultSelectedIndex(this.menuList[i])
|
||||||
|
// 把所有不是默认的为true的点为false
|
||||||
|
for (let j = 0; j < unDefaultSelectedIndexArr.length; j++) {
|
||||||
|
if (this.selectDetailList[unDefaultSelectedIndexArr[j]].isSelected == true) {
|
||||||
|
this.itemTap(unDefaultSelectedIndexArr[j], this.selectDetailList, this.menuList[i].isMutiple, this
|
||||||
|
.menuList[i].key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedObj = this.defaultSelectedObj;
|
||||||
|
this.result = this.defaultSelectedObj;
|
||||||
|
let obj = {
|
||||||
|
'result': this.result,
|
||||||
|
'titles': this.defaultSelectedTitleObj,
|
||||||
|
'isReset': true
|
||||||
|
}
|
||||||
|
this.$emit("confirm", obj);
|
||||||
|
callback(this.result)
|
||||||
|
},
|
||||||
|
getUnDefaultSelectedIndex(menuListItem) { // 获取非默认项
|
||||||
|
let tempDefault = menuListItem.defaultSelectedIndex;
|
||||||
|
if (!Array.isArray(tempDefault)) {
|
||||||
|
tempDefault = [tempDefault];
|
||||||
|
}
|
||||||
|
// 获取所有项的下标 组成新的数组
|
||||||
|
let all = [];
|
||||||
|
for (let i = 0; i < menuListItem.detailList.length; i++) {
|
||||||
|
all.push(i)
|
||||||
|
}
|
||||||
|
// 将默认选中的数组与所有项的数组的不同值合并为一个新数组
|
||||||
|
var unDefaultSelectedIndex = tempDefault.filter(function(v) {
|
||||||
|
return !(all.indexOf(v) > -1)
|
||||||
|
}).concat(all.filter(function(v) {
|
||||||
|
return !(tempDefault.indexOf(v) > -1)
|
||||||
|
}));
|
||||||
|
return unDefaultSelectedIndex;
|
||||||
|
},
|
||||||
|
resetMenuList(val) {
|
||||||
|
this.menuList = val;
|
||||||
|
this.$emit('update:menuList', val)
|
||||||
|
},
|
||||||
|
menuTabClick(index) {
|
||||||
|
this.menuIndex = index;
|
||||||
|
this.selectDetailList = this.menuList[index].detailList;
|
||||||
|
this.selectedKey = this.menuList[index].key;
|
||||||
|
// 如果是独立菜单
|
||||||
|
if (this.independence && !this.menuList[index].isSort) {
|
||||||
|
if (JSON.stringify(this.independenceObj) == '{}') {
|
||||||
|
this.initIndependenceObj(index);
|
||||||
|
} else {
|
||||||
|
for (let key in this.independenceObj) {
|
||||||
|
if (key != this.selectedKey) {
|
||||||
|
this.initIndependenceObj(index);
|
||||||
|
this.resetSelected(this.menuList[index].detailList, this.selectedKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (this.independence && this.menuList[index].isSort) {
|
||||||
|
|
||||||
|
this.independenceObj = {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
if (this.independence) {
|
||||||
|
let idx = this.menuList[index].defaultSelectedIndex;
|
||||||
|
if (idx != null && idx.toString().length > 0) { // 处理独立菜单默认值
|
||||||
|
if (this.menuList[index].isMutiple) {
|
||||||
|
for (let i = 0; i < idx.length; i++) {
|
||||||
|
if (this.menuList[index].detailList[idx[i]].isSelected == false) {
|
||||||
|
this.itemTap(idx[i], this.menuList[index].detailList, true, this.selectedKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.menuList[index].detailList[idx].isSelected == false) {
|
||||||
|
|
||||||
|
this.itemTap(idx, this.menuList[index].detailList, false, this.selectedKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
this.selectedObj = this.selectedObj;
|
||||||
|
this.$forceUpdate();
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
initIndependenceObj(index) {
|
||||||
|
this.independenceObj = {};
|
||||||
|
if (this.menuList[index].isMutiple) {
|
||||||
|
this.independenceObj[this.selectedKey] = [];
|
||||||
|
} else {
|
||||||
|
this.independenceObj[this.selectedKey] = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemTap(index, list, isMutiple, key) {
|
||||||
|
if (isMutiple == true) {
|
||||||
|
list[index].isSelected = !list[index].isSelected;
|
||||||
|
if (index == 0) {
|
||||||
|
this.resetSelected(list, key)
|
||||||
|
if (!this.independence) {
|
||||||
|
this.selectedTitleObj[key] = list[index].title;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list[0].isSelected = false
|
||||||
|
if (list[index].isSelected) {
|
||||||
|
if (this.independence) {
|
||||||
|
this.independenceObj[this.selectedKey].push(list[index].value);
|
||||||
|
} else {
|
||||||
|
this.selectedObj[key].push(list[index].value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list[index].isSelected = false;
|
||||||
|
if (this.independence) {
|
||||||
|
var idx = this.independenceObj[this.selectedKey].indexOf(list[index].value);
|
||||||
|
this.independenceObj[this.selectedKey].splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
var idx = this.selectedObj[key].indexOf(list[index].value);
|
||||||
|
this.selectedObj[key].splice(idx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (this.independence) {
|
||||||
|
this.result = this.independenceObj;
|
||||||
|
} else {
|
||||||
|
this.result = this.selectedObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index == 0) {
|
||||||
|
this.resetSelected(list, key)
|
||||||
|
if (!this.independence) {
|
||||||
|
this.selectedTitleObj[key] = list[index].title;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list[0].isSelected = false
|
||||||
|
if (this.independence) {
|
||||||
|
this.independenceObj[this.selectedKey] = list[index].value;
|
||||||
|
this.result = this.independenceObj;
|
||||||
|
} else {
|
||||||
|
this.selectedObj[key] = list[index].value;
|
||||||
|
this.result = this.selectedObj;
|
||||||
|
this.selectedTitleObj[key] = list[index].title;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (index == i) {
|
||||||
|
list[i].isSelected = true
|
||||||
|
} else {
|
||||||
|
list[i].isSelected = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #ifdef H5
|
||||||
|
this.$forceUpdate();
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
resetSelected(list, key) {
|
||||||
|
if (typeof this.result[key] == 'object') {
|
||||||
|
this.result[key] = [];
|
||||||
|
this.selectedTitleObj[key] = list[0].title;
|
||||||
|
} else {
|
||||||
|
this.result[key] = '';
|
||||||
|
this.selectedTitleObj[key] = list[0].title;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
list[i].isSelected = true;
|
||||||
|
} else {
|
||||||
|
list[i].isSelected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #ifdef H5
|
||||||
|
this.$forceUpdate();
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
sortTap(index, list, key) {
|
||||||
|
if (this.independence) {
|
||||||
|
this.independenceObj[this.selectedKey] = list[index].value;
|
||||||
|
this.result = this.independenceObj;
|
||||||
|
} else {
|
||||||
|
this.selectedObj[key] = list[index].value;
|
||||||
|
this.result = this.selectedObj;
|
||||||
|
this.selectedTitleObj[key] = list[index].title;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (index == i) {
|
||||||
|
list[i].isSelected = true;
|
||||||
|
} else {
|
||||||
|
list[i].isSelected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let obj = {
|
||||||
|
'result': this.result,
|
||||||
|
'titles': this.selectedTitleObj,
|
||||||
|
'isReset': false
|
||||||
|
}
|
||||||
|
this.$emit("confirm", obj);
|
||||||
|
},
|
||||||
|
sureClick() {
|
||||||
|
let obj = {
|
||||||
|
'result': this.result,
|
||||||
|
'titles': this.selectedTitleObj,
|
||||||
|
'isReset': false
|
||||||
|
}
|
||||||
|
this.$emit("confirm", obj);
|
||||||
|
},
|
||||||
|
resetClick(list, key) {
|
||||||
|
this.resetSelected(list, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.filter-content {
|
||||||
|
background-color: #F6F7F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-title {
|
||||||
|
border-bottom: #EEEEEE 1px solid;
|
||||||
|
padding: 10px 15px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-detail {
|
||||||
|
padding: 5px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-detail scroll-view {
|
||||||
|
max-height: 400upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-detail-item-active {
|
||||||
|
background-color: #D1372C;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-detail-item-default {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
color: #666666;
|
||||||
|
padding: 5px 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 45px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-footer-item {
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-list {
|
||||||
|
|
||||||
|
padding: 5px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-list-item-default {
|
||||||
|
color: #666666;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-list-item-default text {
|
||||||
|
width: 90%;
|
||||||
|
font-size: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-list-item-active {
|
||||||
|
color: #D1372C;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-list-item-active text {
|
||||||
|
font-size: 14px;
|
||||||
|
width: 90%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-content-list-item-active:after {
|
||||||
|
content: '✓';
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: 'sl-font';
|
||||||
|
src: url('data:font/truetype;charset=utf-8;base64,AAEAAAALAIAAAwAwR1NVQrD+s+0AAAE4AAAAQk9TLzI8kEgOAAABfAAAAFZjbWFwZO3RAgAAAeAAAAGGZ2x5Zh0ZI/EAAANwAAAAyGhlYWQVZkUXAAAA4AAAADZoaGVhB94DhAAAALwAAAAkaG10eAwAAAAAAAHUAAAADGxvY2EAMgBkAAADaAAAAAhtYXhwAREAKAAAARgAAAAgbmFtZT5U/n0AAAQ4AAACbXBvc3TohGjqAAAGqAAAADMAAQAAA4D/gABcBAAAAAAABAAAAQAAAAAAAAAAAAAAAAAAAAMAAQAAAAEAANxW6kVfDzz1AAsEAAAAAADZJADbAAAAANkkANsAAAAABAACZAAAAAgAAgAAAAAAAAABAAAAAwAcAAQAAAAAAAIAAAAKAAoAAAD/AAAAAAAAAAEAAAAKAB4ALAABREZMVAAIAAQAAAAAAAAAAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAQAGAAAAAQAAAAAAAQQAAZAABQAIAokCzAAAAI8CiQLMAAAB6wAyAQgAAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA5hrmHAOA/4AAXAOAAIAAAAABAAAAAAAABAAAAAQAAAAEAAAAAAAABQAAAAMAAAAsAAAABAAAAV4AAQAAAAAAWAADAAEAAAAsAAMACgAAAV4ABAAsAAAABgAEAAEAAuYa5hz//wAA5hrmHP//AAAAAAABAAYABgAAAAEAAgAAAQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAKAAAAAAAAAACAADmGgAA5hoAAAABAADmHAAA5hwAAAACAAAAAAAAADIAZAAEAAAAAAOlAmQAEwAWABkAGgAAEwEWMjcBNjIWFAcBBiInASY0NjIBMDEVMDEnmQFgAgoDAV8LHRUK/n8LHAv+fwoVHQFoAQJZ/qEDAwFfCxYcC/6ACwsBgAsdFf6bAgQAAAAABAAAAAADpAJkABMAFgAZABsAACUBJiIHAQYiJjQ3ATYyFwEWFAYiATAxNTAxFzEDZ/6hAwoD/qELHRUKAYELHAsBgQoVHf6YAacBXwMD/qELFhwLAYEKCv5/CxwWAWUCBAAAAAAAEgDeAAEAAAAAAAAAFQAAAAEAAAAAAAEACAAVAAEAAAAAAAIABwAdAAEAAAAAAAMACAAkAAEAAAAAAAQACAAsAAEAAAAAAAUACwA0AAEAAAAAAAYACAA/AAEAAAAAAAoAKwBHAAEAAAAAAAsAEwByAAMAAQQJAAAAKgCFAAMAAQQJAAEAEACvAAMAAQQJAAIADgC/AAMAAQQJAAMAEADNAAMAAQQJAAQAEADdAAMAAQQJAAUAFgDtAAMAAQQJAAYAEAEDAAMAAQQJAAoAVgETAAMAAQQJAAsAJgFpCkNyZWF0ZWQgYnkgaWNvbmZvbnQKaWNvbmZvbnRSZWd1bGFyaWNvbmZvbnRpY29uZm9udFZlcnNpb24gMS4waWNvbmZvbnRHZW5lcmF0ZWQgYnkgc3ZnMnR0ZiBmcm9tIEZvbnRlbGxvIHByb2plY3QuaHR0cDovL2ZvbnRlbGxvLmNvbQAKAEMAcgBlAGEAdABlAGQAIABiAHkAIABpAGMAbwBuAGYAbwBuAHQACgBpAGMAbwBuAGYAbwBuAHQAUgBlAGcAdQBsAGEAcgBpAGMAbwBuAGYAbwBuAHQAaQBjAG8AbgBmAG8AbgB0AFYAZQByAHMAaQBvAG4AIAAxAC4AMABpAGMAbwBuAGYAbwBuAHQARwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABzAHYAZwAyAHQAdABmACAAZgByAG8AbQAgAEYAbwBuAHQAZQBsAGwAbwAgAHAAcgBvAGoAZQBjAHQALgBoAHQAdABwADoALwAvAGYAbwBuAHQAZQBsAGwAbwAuAGMAbwBtAAAAAAIAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwECAQMBBAAEZG93bgJ1cAAAAA==') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.sl-font {
|
||||||
|
font-family: "sl-font" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sl-down:before {
|
||||||
|
content: "\e61a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.sl-up:before {
|
||||||
|
content: "\e61c";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
<template>
|
||||||
|
<scroll-view scroll-y v-show="ifshow" @tap="ableClose" @touchmove.stop.prevent class="popup-layer">
|
||||||
|
<view ref="popRef" class="popup-content" @tap.stop="stopEvent" :style="_location">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'popup-layer',
|
||||||
|
props: {
|
||||||
|
direction: {
|
||||||
|
type: String,
|
||||||
|
default: 'top', // 方向 top,bottom,left,right
|
||||||
|
},
|
||||||
|
autoClose: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
isTransNav: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
navHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
ifshow: false, // 是否展示,
|
||||||
|
translateValue: -100, // 位移距离
|
||||||
|
timer: null,
|
||||||
|
iftoggle: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
_translate() {
|
||||||
|
if (this.isTransNav) {
|
||||||
|
const transformObj = {
|
||||||
|
'top': `transform:translateY(${-this.translateValue}%)`,
|
||||||
|
'bottom': `transform:translateY(calc(${this.translateValue}% + ${this.navHeight}px))`,
|
||||||
|
'left': `transform:translateX(${-this.translateValue}%)`,
|
||||||
|
'right': `transform:translateX(${this.translateValue}%)`
|
||||||
|
};
|
||||||
|
return transformObj[this.direction]
|
||||||
|
} else {
|
||||||
|
const transformObj = {
|
||||||
|
'top': `transform:translateY(${-this.translateValue}%)`,
|
||||||
|
'bottom': `transform:translateY(${this.translateValue}%)`,
|
||||||
|
'left': `transform:translateX(${-this.translateValue}%)`,
|
||||||
|
'right': `transform:translateX(${this.translateValue}%)`
|
||||||
|
};
|
||||||
|
return transformObj[this.direction]
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
_location() {
|
||||||
|
const positionValue = {
|
||||||
|
'top': 'bottom:0px;width:100%;',
|
||||||
|
'bottom': 'top:0px;width:100%;',
|
||||||
|
'left': 'right:0px;height:100%;',
|
||||||
|
'right': 'left:0px;height:100%;',
|
||||||
|
};
|
||||||
|
return positionValue[this.direction] + this._translate;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
show() {
|
||||||
|
let _this = this;
|
||||||
|
this.ifshow = true;
|
||||||
|
let _open = setTimeout(() => {
|
||||||
|
this.translateValue = 0;
|
||||||
|
_open = null;
|
||||||
|
}, 100)
|
||||||
|
let _toggle = setTimeout(() => {
|
||||||
|
this.iftoggle = true;
|
||||||
|
_toggle = null;
|
||||||
|
}, 300);
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
if (this.timer !== null || !this.iftoggle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.translateValue = -100 - this.navHeight;
|
||||||
|
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.ifshow = false;
|
||||||
|
this.timer = null;
|
||||||
|
this.iftoggle = false;
|
||||||
|
}, 300);
|
||||||
|
this.$emit("close")
|
||||||
|
},
|
||||||
|
ableClose() {
|
||||||
|
if (this.autoClose) {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stopEvent(event) {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.popup-layer {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999999;
|
||||||
|
background: rgba(0, 0, 0, .3);
|
||||||
|
height: calc(100% - 50px);
|
||||||
|
width: 100%;
|
||||||
|
left: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000000;
|
||||||
|
background: #FFFFFF;
|
||||||
|
transition: all .3s ease;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,308 @@
|
||||||
|
<template>
|
||||||
|
<view class="content">
|
||||||
|
<view :style="{height: tabHeight +'px'}">
|
||||||
|
<view :class="topFixed?'select-tab-fixed-top':'select-tab'" :style="{height: tabHeight+'px'}">
|
||||||
|
<view class="select-tab-item" :style="{width: itemWidth}" v-for="(item,index) in titleList" :key="index" @tap="showMenuClick(index)">
|
||||||
|
<text :style="{color:color}">{{item.title}}</text>
|
||||||
|
<text class="arrows sl-font" :class="statusList[index].isActive?up:down"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<popup-layer ref="popupRef" :direction="'bottom'" @close="close" :isTransNav="isTransNav" :navHeight="navHeight"
|
||||||
|
:tabHeight="tabHeight">
|
||||||
|
<sl-filter-view :ref="'slFilterView'" :independence="independence" :themeColor="themeColor" :menuList.sync="menuListTemp"
|
||||||
|
ref="slFilterView" @confirm="filterResult"></sl-filter-view>
|
||||||
|
</popup-layer>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import popupLayer from '@/components/sl-filter/popup-layer.vue';
|
||||||
|
import slFilterView from '@/components/sl-filter/filter-view.vue';
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
popupLayer,
|
||||||
|
slFilterView
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
menuList: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
themeColor: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '#000000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '#666666'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
independence: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isTransNav: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
navHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
topFixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
tabHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 50
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
itemWidth() {
|
||||||
|
// return 'calc(100%/2)'
|
||||||
|
return 'auto'
|
||||||
|
},
|
||||||
|
menuListTemp: {
|
||||||
|
get() {
|
||||||
|
return this.getMenuListTemp();
|
||||||
|
},
|
||||||
|
set(newObj) {
|
||||||
|
return newObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// #ifndef H5
|
||||||
|
onReady: function() {
|
||||||
|
let arr = [];
|
||||||
|
let titleArr = [];
|
||||||
|
let r = {};
|
||||||
|
for (let i = 0; i < this.menuList.length; i++) {
|
||||||
|
arr.push({
|
||||||
|
'isActive': false
|
||||||
|
});
|
||||||
|
// titleArr.push({
|
||||||
|
// 'title': this.menuList[i].title,
|
||||||
|
// 'key': this.menuList[i].key
|
||||||
|
// })
|
||||||
|
|
||||||
|
r[this.menuList[i].key] = this.menuList[i].title;
|
||||||
|
|
||||||
|
if (this.menuList[i].reflexTitle && this.menuList[i].defaultSelectedIndex > -1) {
|
||||||
|
titleArr.push({
|
||||||
|
'title': this.menuList[i].detailList[this.menuList[i].defaultSelectedIndex].title,
|
||||||
|
'key': this.menuList[i].key
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
titleArr.push({
|
||||||
|
'title': this.menuList[i].title,
|
||||||
|
'key': this.menuList[i].key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this.statusList = arr;
|
||||||
|
this.titleList = titleArr;
|
||||||
|
this.tempTitleObj = r;
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
created: function() {
|
||||||
|
let arr = [];
|
||||||
|
let titleArr = [];
|
||||||
|
let r = {};
|
||||||
|
for (let i = 0; i < this.menuList.length; i++) {
|
||||||
|
arr.push({
|
||||||
|
'isActive': false
|
||||||
|
});
|
||||||
|
// titleArr.push({
|
||||||
|
// 'title': this.menuList[i].title,
|
||||||
|
// 'key': this.menuList[i].key
|
||||||
|
// });
|
||||||
|
r[this.menuList[i].key] = this.menuList[i].title;
|
||||||
|
|
||||||
|
if (this.menuList[i].reflexTitle && this.menuList[i].defaultSelectedIndex > -1) {
|
||||||
|
titleArr.push({
|
||||||
|
'title': this.menuList[i].detailList[this.menuList[i].defaultSelectedIndex].title,
|
||||||
|
'key': this.menuList[i].key
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
titleArr.push({
|
||||||
|
'title': this.menuList[i].title,
|
||||||
|
'key': this.menuList[i].key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this.statusList = arr;
|
||||||
|
this.titleList = titleArr;
|
||||||
|
this.tempTitleObj = r;
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
down: 'sl-down',
|
||||||
|
up: 'sl-up',
|
||||||
|
// tabHeight: 50,
|
||||||
|
statusList: [],
|
||||||
|
selectedIndex: '',
|
||||||
|
titleList: [],
|
||||||
|
tempTitleObj: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getMenuListTemp() {
|
||||||
|
let arr = this.menuList;
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
let item = arr[i];
|
||||||
|
for (let j = 0; j < item.detailList.length; j++) {
|
||||||
|
let d_item = item.detailList[j];
|
||||||
|
if (j == 0) {
|
||||||
|
d_item.isSelected = true
|
||||||
|
} else {
|
||||||
|
d_item.isSelected = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
},
|
||||||
|
// 重置所有选项,包括默认选项,并更新result
|
||||||
|
resetAllSelect(callback) {
|
||||||
|
this.$refs.slFilterView.resetAllSelect(function(e){
|
||||||
|
callback(e);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 重置选项为设置的默认值,并更新result
|
||||||
|
resetSelectToDefault(callback) {
|
||||||
|
this.$refs.slFilterView.resetSelectToDefault(function(e){
|
||||||
|
callback(e);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
resetMenuList(val) {
|
||||||
|
this.menuList = val;
|
||||||
|
this.$emit('update:menuList', val)
|
||||||
|
this.$forceUpdate();
|
||||||
|
this.$refs.slFilterView.resetMenuList(val)
|
||||||
|
},
|
||||||
|
showMenuClick(index) {
|
||||||
|
this.selectedIndex = index;
|
||||||
|
if (this.statusList[index].isActive == true) {
|
||||||
|
this.$refs.popupRef.close();
|
||||||
|
this.statusList[index].isActive = false
|
||||||
|
} else {
|
||||||
|
this.menuTabClick(index);
|
||||||
|
this.$refs.popupRef.show()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
menuTabClick(index) {
|
||||||
|
this.$refs.slFilterView.menuTabClick(index);
|
||||||
|
for (let i = 0; i < this.statusList.length; i++) {
|
||||||
|
if (index == i) {
|
||||||
|
this.statusList[i].isActive = true;
|
||||||
|
} else {
|
||||||
|
this.statusList[i].isActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filterResult(obj) {
|
||||||
|
let val = obj.result;
|
||||||
|
let titlesObj = obj.titles;
|
||||||
|
// 处理选项映射到菜单title
|
||||||
|
if (this.independence) {
|
||||||
|
if (!this.menuList[this.selectedIndex].isMutiple || this.menuList[this.selectedIndex].isSort) {
|
||||||
|
let tempTitle = '';
|
||||||
|
for (let i = 0; i < this.menuList[this.selectedIndex].detailList.length; i++) {
|
||||||
|
let item = this.menuList[this.selectedIndex].detailList[i];
|
||||||
|
if (item.value == val[this.menuList[this.selectedIndex].key]) {
|
||||||
|
tempTitle = item.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.menuList[this.selectedIndex].reflexTitle) {
|
||||||
|
this.titleList[this.selectedIndex].title = tempTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let key in titlesObj) {
|
||||||
|
if (!Array.isArray(titlesObj[key])) {
|
||||||
|
this.tempTitleObj[key] = titlesObj[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
for (let key in this.tempTitleObj) {
|
||||||
|
for (let i = 0; i < this.titleList.length; i++) {
|
||||||
|
if (this.titleList[i].key == key) {
|
||||||
|
this.titleList[i].title = this.tempTitleObj[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$refs.popupRef.close()
|
||||||
|
if (obj.isReset) {
|
||||||
|
|
||||||
|
} else{
|
||||||
|
this.$emit("result", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
for (let i = 0; i < this.statusList.length; i++) {
|
||||||
|
this.statusList[i].isActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import 'iconfont/iconfont.css';
|
||||||
|
|
||||||
|
.select-tab {
|
||||||
|
/* border-bottom: #F7F7F7 1px solid; */
|
||||||
|
/* background-color: #FFFFFF; */
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-tab-fixed-top {
|
||||||
|
/* border-bottom: #F7F7F7 1px solid; */
|
||||||
|
/* background-color: #FFFFFF; */
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
/* #ifdef H5 */
|
||||||
|
top: 44px;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef H5 */
|
||||||
|
top: 0;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrows {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-tab .select-tab-item,
|
||||||
|
.select-tab-fixed-top .select-tab-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 30upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-tab .select-tab-item text,
|
||||||
|
.select-tab-fixed-top .select-tab-item text {
|
||||||
|
color: #666666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<view v-if="videoShow" class="pos-f pos-full x-c" style="background: #000; z-index: 99999;" @dblclick="videoExit">
|
||||||
|
<video @play="videoPlay" @pause="videoPause" @ended="videoEnded" @click="videoTap"
|
||||||
|
@fullscreenchange="videoChange" autoplay enable-play-gesture id="use-video" :src="src"
|
||||||
|
:vslide-gesture-in-fullscreen="false" :direction="0" :show-play-btn="false" :show-fullscreen-btn="false"
|
||||||
|
style="width: 100%;height: 100%;"></video>
|
||||||
|
|
||||||
|
<!-- 暂停播放图标 -->
|
||||||
|
<cover-image v-if="videoShow && !videoPlaying" src="/static//common/bofang.svg"
|
||||||
|
class="border-radius-c pos-a pos-tl-c x-c" style="width: 100rpx; height: 100rpx;" @click="videoTap">
|
||||||
|
</cover-image>
|
||||||
|
|
||||||
|
<!-- 关闭按钮 -->
|
||||||
|
<cover-image v-if="videoShow" src="/static/common/close.png"
|
||||||
|
class="border-radius-c pos-a pos-bottom pos-right x-c use-close" @click="videoExit"></cover-image>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "use-video",
|
||||||
|
props: {
|
||||||
|
src: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
videoShow: false,
|
||||||
|
videoContext: null,
|
||||||
|
videoPlaying: false,
|
||||||
|
videoDblClick: false,
|
||||||
|
touchTime: new Date().getTime()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(val) {
|
||||||
|
console.log('watch', val);
|
||||||
|
this.videoShow = val;
|
||||||
|
if(val) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.videoPlay()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* @description 超时
|
||||||
|
*/
|
||||||
|
timerout(callback, timer = 1000) {
|
||||||
|
let _timer = setTimeout(() => {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
clearTimeout(_timer);
|
||||||
|
}, timer);
|
||||||
|
},
|
||||||
|
videoPlay(event) {
|
||||||
|
console.log('video-play', event);
|
||||||
|
this.videoPlaying = true;
|
||||||
|
},
|
||||||
|
videoPause(event) {
|
||||||
|
console.log('video-pause', event);
|
||||||
|
this.videoPlaying = false;
|
||||||
|
},
|
||||||
|
videoEnded(event) {
|
||||||
|
console.log('video-ended', event);
|
||||||
|
},
|
||||||
|
videoTap(event) {
|
||||||
|
console.log('video-tap', event);
|
||||||
|
this.videoDblClick = false;
|
||||||
|
|
||||||
|
this.timerout(() => {
|
||||||
|
if (new Date().getTime() - this.touchTime < 260) {
|
||||||
|
this.videoDblClick = true;
|
||||||
|
console.log('dblclick', this.videoContext);
|
||||||
|
|
||||||
|
this.videoExit();
|
||||||
|
} else if (!this.videoDblClick) {
|
||||||
|
console.log('click', this.videoContext);
|
||||||
|
|
||||||
|
if (this.videoPlaying) {
|
||||||
|
this.videoContext.pause();
|
||||||
|
} else {
|
||||||
|
this.videoContext.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 260);
|
||||||
|
|
||||||
|
this.touchTime = new Date().getTime();
|
||||||
|
},
|
||||||
|
videoExit() {
|
||||||
|
this.videoContext.stop();
|
||||||
|
this.videoContext.pause();
|
||||||
|
this.videoShow = false;
|
||||||
|
this.$emit('exit');
|
||||||
|
},
|
||||||
|
videoChange(event) {
|
||||||
|
console.log('video-change', event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.videoShow = this.value;
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.videoContext = uni.createVideoContext('use-video', this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.pos-a {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pos-f {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.pos-right {right: 0}
|
||||||
|
|
||||||
|
.pos-tl-c {
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pos-bottom {
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pos-full {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-radius-c {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.use-close {
|
||||||
|
right: 30rpx;
|
||||||
|
bottom: 88rpx;
|
||||||
|
width: 68rpx;
|
||||||
|
height: 68rpx;
|
||||||
|
background: rgba(0, 0, 0, .58);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
/**
|
||||||
|
* 插入loading
|
||||||
|
*/
|
||||||
|
const insertDom = (el) => {
|
||||||
|
let dom = `<div class="el-loading-mask">
|
||||||
|
<div class="el-loading-spinner">
|
||||||
|
<svg viewBox="25 25 50 50" class="circular">
|
||||||
|
<circle cx="50" cy="50" r="20" fill="none" class="path"> </circle>
|
||||||
|
</svg>
|
||||||
|
<p class="el-loading-text">拼命加载中...</p>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
//el添加相对定位
|
||||||
|
el.classList.add('el-loading-parent--relative');
|
||||||
|
|
||||||
|
// 插入到被绑定的元素内部
|
||||||
|
el.insertAdjacentHTML('afterbegin', dom);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除loading
|
||||||
|
*/
|
||||||
|
const removeDom = (el) => {
|
||||||
|
const ds = el.getElementsByClassName('el-loading-mask')[0];
|
||||||
|
if (ds) {
|
||||||
|
el.removeChild(ds);
|
||||||
|
el.classList.remove('el-loading-parent--relative');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新是否显示
|
||||||
|
const toggleLoading = (el, binding) => {
|
||||||
|
if (binding.value) {
|
||||||
|
insertDom(el);
|
||||||
|
} else {
|
||||||
|
removeDom(el);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Vue.directive('loading', {
|
||||||
|
bind: function(el, binding, vnode) {
|
||||||
|
toggleLoading(el, binding);
|
||||||
|
},
|
||||||
|
//所在组件的 VNode 更新时调用--比较更新前后的值
|
||||||
|
update: function(el, binding) {
|
||||||
|
if (binding.oldValue !== binding.value) {
|
||||||
|
toggleLoading(el, binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
/deep/ .el-loading-parent--relative {
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-loading-mask {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2000;
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
|
margin: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
|
||||||
|
.el-loading-spinner {
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -21px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .el-loading-text {
|
||||||
|
color: #409eff;
|
||||||
|
margin: 3px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .circular {
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
|
animation: loading-rotate 2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner .path {
|
||||||
|
animation: loading-dash 1.5s ease-in-out infinite;
|
||||||
|
stroke-dasharray: 90, 150;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke: #409eff;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-spinner i {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-loading-fade-enter,
|
||||||
|
.el-loading-fade-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loading-rotate {
|
||||||
|
to {
|
||||||
|
transform: rotate(1turn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loading-dash {
|
||||||
|
0% {
|
||||||
|
stroke-dasharray: 1, 200;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke-dasharray: 90, 150;
|
||||||
|
stroke-dashoffset: -40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
stroke-dasharray: 90, 150;
|
||||||
|
stroke-dashoffset: -120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||||
|
CSS.supports('top: constant(a)'))
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
|
</script>
|
||||||
|
<title></title>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
// #ifndef VUE3
|
||||||
|
import uView from '@/uni_modules/uview-ui'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import App from './App'
|
||||||
|
import myMixin from 'mixin/mixin.js'
|
||||||
|
|
||||||
|
// main.js
|
||||||
|
Vue.use(uView)
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
import store from './store'
|
||||||
|
|
||||||
|
// 混入,全局引用
|
||||||
|
Vue.mixin(myMixin);
|
||||||
|
|
||||||
|
App.mpType = 'app'
|
||||||
|
|
||||||
|
const app = new Vue({
|
||||||
|
store,
|
||||||
|
...App
|
||||||
|
})
|
||||||
|
app.$mount()
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
import { createSSRApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
export function createApp() {
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
return {
|
||||||
|
app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"name" : "shortPlay-mini",
|
||||||
|
"appid" : "__UNI__D43C3F5",
|
||||||
|
"description" : "",
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : "100",
|
||||||
|
"transformPx" : false,
|
||||||
|
"app-plus" : {
|
||||||
|
/* 5+App特有相关 */
|
||||||
|
"usingComponents" : true,
|
||||||
|
"nvueCompiler" : "uni-app",
|
||||||
|
"nvueStyleCompiler" : "uni-app",
|
||||||
|
"splashscreen" : {
|
||||||
|
"alwaysShowBeforeRender" : true,
|
||||||
|
"waiting" : true,
|
||||||
|
"autoclose" : true,
|
||||||
|
"delay" : 0
|
||||||
|
},
|
||||||
|
"modules" : {},
|
||||||
|
/* 模块配置 */
|
||||||
|
"distribute" : {
|
||||||
|
/* 应用发布信息 */
|
||||||
|
"android" : {
|
||||||
|
/* android打包配置 */
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ios" : {},
|
||||||
|
/* ios打包配置 */
|
||||||
|
"sdkConfigs" : {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* SDK配置 */
|
||||||
|
"quickapp" : {},
|
||||||
|
/* 快应用特有相关 */
|
||||||
|
"mp-weixin" : {
|
||||||
|
/* 小程序特有相关 */
|
||||||
|
"appid" : "wx0e233b84fa447fb4",
|
||||||
|
"setting" : {
|
||||||
|
"urlCheck" : false
|
||||||
|
},
|
||||||
|
"usingComponents" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
navigateTo(url) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
navigateBack() {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,316 @@
|
||||||
|
{
|
||||||
|
// 如果您是通过uni_modules形式引入uView,可以忽略此配置
|
||||||
|
"easycom": {
|
||||||
|
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
|
||||||
|
},
|
||||||
|
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "pages/start/start",
|
||||||
|
"style": {
|
||||||
|
"enablePullDownRefresh": false,
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// #ifdef H5
|
||||||
|
{
|
||||||
|
"path": "pages/home/h5/h5",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "种草短剧",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/shortPlay/shortPlay",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "变现",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/my/h5/h5",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
{
|
||||||
|
"path": "pages/home/mini/mini",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "种草短剧",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/home/mini/info/info",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/shortPlay/shortPlay",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "短剧",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/my/mini/mini",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "我的",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/wallet/wallet",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "我的钱包",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/data/shortPlay/shortPlay",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "短剧数据",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/task/task",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "任务",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/shortPlay/info/info",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "详情",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/account/account",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "账号管理",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/inviteFriend/inviteFriend",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "邀请好友",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/wallet/bindBankCard/bindBankCard",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "绑定银行卡",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/wallet/bindAlipay/bindAlipay",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "绑定支付宝",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/wallet/withdrawalRecord/withdrawalRecord",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "提现记录",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
{
|
||||||
|
"path": "pages/entry/entry",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "登录",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/login/login",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "登录",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/register/register",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "注册"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"path": "pages/index/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "uni-app"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/agreement/user/user",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "用户协议",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/agreement/privacy/privacy",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "隐私政策",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/notice/notice",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "公告列表",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/personal/personal",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "个人信息",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// "path" : "pages/my/updatePwd/updatePwd",
|
||||||
|
// "style" :
|
||||||
|
// {
|
||||||
|
// "navigationBarTitleText" : "修改密码",
|
||||||
|
// "enablePullDownRefresh" : false
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
"path" : "pages/data/data",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "种草短剧",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/login/forgetPwd/forgetPwd",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "忘记密码",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/notice/info/info",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/home/mini/viewImg/viewImg",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "种草短剧",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/feedback/feedback",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "意见反馈",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/my/feedback/add/add",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "意见反馈",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path" : "pages/task/info/info",
|
||||||
|
"style" :
|
||||||
|
{
|
||||||
|
"navigationBarTitleText" : "任务详情",
|
||||||
|
"enablePullDownRefresh" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// #ifdef H5
|
||||||
|
"tabBar": {
|
||||||
|
"color": "#7A7E83",
|
||||||
|
"selectedColor": "#969799",
|
||||||
|
"borderStyle": "black",
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
"list": [{
|
||||||
|
"pagePath": "pages/home/h5/h5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/shortPlay/shortPlay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/my/h5/h5"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
"tabBar": {
|
||||||
|
"color": "#7A7E83",
|
||||||
|
"selectedColor": "#969799",
|
||||||
|
"borderStyle": "black",
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
"list": [{
|
||||||
|
"pagePath": "pages/home/mini/mini"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/shortPlay/shortPlay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/data/data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/task/task"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/my/mini/mini"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
// #969799
|
||||||
|
"globalStyle": {
|
||||||
|
"navigationBarTextStyle": "black",
|
||||||
|
"navigationBarTitleText": "uni-app",
|
||||||
|
"navigationBarBackgroundColor": "#F8F8F8",
|
||||||
|
"backgroundColor": "#f7f8fa",
|
||||||
|
"app-plus": {
|
||||||
|
"background": "#efeff4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,298 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<view v-html="html"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
html: `
|
||||||
|
<div class="box" data-v-4003a248=""><div class="text" data-v-4003a248=""><p style="text-align: center;"><strong>【种草短剧</strong><strong>】隐私权政策</strong></p>
|
||||||
|
<p style="text-align: right;">版本更新日期:【2023】年【05】月【19】日</p>
|
||||||
|
<p><strong>本政策适用于【种草达人科技(深圳)有限公司】(“</strong><strong>我们”</strong><strong>或“</strong><strong>公司”</strong><strong>)提供的【种草短剧</strong><strong>】及相关服务(“</strong><strong>本产品”</strong><strong>),旨在说明在您使用我们的服务时,我们将如何处理您的个人信息,以及您对这些个人信息享有的权利。</strong></p>
|
||||||
|
<p><strong>请仔细阅读本政策并确定理解我们对您个人信息的处理规则。阅读过程中,如对本政策内容有任何疑问、意见或建议,您可按照本政策尾页中提供的联系方式与我们联系。如您不理解或不同意本政策中的任何条款,您应立即停止使用。一旦您开始使用本产品,即表示您已充分理解并同意本政策。</strong></p>
|
||||||
|
<p><strong>请注意,我们不控制第三方,本政策在任何情况下均不适用于第三方。第三方对您个人信息的收集与使用将遵守第三方的个人信息保护政策。我们建议您在访问第三方时仔细阅读并了解他们的个人信息政策。本政策将帮助您了解以下内容:</strong></p>
|
||||||
|
<p><strong>一、我们如何收集和使用您的个人信息</strong></p>
|
||||||
|
<p><strong>二、我们如何共享、转让、公开披露您的个人信息</strong></p>
|
||||||
|
<p><strong>三、我们如何存储和保护您的个人信息</strong></p>
|
||||||
|
<p><strong>四、您如何管理您的个人信息</strong></p>
|
||||||
|
<p><strong>五、未成年人的个人信息保护</strong></p>
|
||||||
|
<p><strong>六、通知和修订</strong></p>
|
||||||
|
<p><strong>七、如何联系我们</strong></p>
|
||||||
|
<p><strong>一、我们如何收集和使用您的个人信息</strong></p>
|
||||||
|
<p><strong>(一)您需要授权我们收集和使用您个人信息的场景</strong></p>
|
||||||
|
<table>
|
||||||
|
<tbody style="width: 100%;border-collapse: collapse;">
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>我们收集的个人信息</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p><strong>使用目的</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p><strong>收集场景</strong></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>帐号注册信息及联系方式</strong></p>
|
||||||
|
<p><strong>包括:微信昵称、微信平台用户ID</strong><strong>、微信平台unionid</strong><strong>、手机号码</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p> </p>
|
||||||
|
<p>用于成为用户、用户登录以及与用户沟通或互动</p>
|
||||||
|
<p> </p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>手机号码及验证信息</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p> </p>
|
||||||
|
<p>用于成为用户及用户登录以及与用户沟通或互动</p>
|
||||||
|
<p> </p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>个人网络信息(IP</strong><strong>地址、Wifi</strong><strong>信息、基站信息等相关信息)</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于与用户提供服务、与用户沟通联系、改善服务质量等目的</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录/使用</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>个人常用设备信息</strong>(包括设备标识符【IMEI、IDFA、Android ID、MAC、OAID 等相关信息】、应用信息【应用崩溃信息、通知开关状态、软件列表等相关信息】、设备参数及系统信息【设备类型、设备型号、操作系统及硬件相关信息】)</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于保障服务安全所必须的功能</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录/使用</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong><u>身份信息</u></strong></p>
|
||||||
|
<p><strong><u>包括:姓名、公民身份号码</u></strong></p>
|
||||||
|
</td>
|
||||||
|
<td rowspan="2" width="184">
|
||||||
|
<p> </p>
|
||||||
|
<p>用于分配用户获得合作收益</p>
|
||||||
|
<p> </p>
|
||||||
|
</td>
|
||||||
|
<td rowspan="2" width="184">
|
||||||
|
<p>合作费提现</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong><u>财产信息</u></strong></p>
|
||||||
|
<p><strong><u>包括:银行账户信息、卡号</u></strong></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>第三方账号信息</strong></p>
|
||||||
|
<p>包括用户第三方账号及昵称、用户第三方账号unionid、用户第三方账号openid、手机号、实名信息(含姓名、公民身份号码)、结算账户信息(含银行账户信息、卡号、第三方支付账号信息)</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于第三方平台账号验证绑定、授权,以及查询抖音号用户信息、视频信息、订单数据、橱窗管理、结算合作收益</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>第三方账号管理及结算合作收益</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>反馈信息</strong></p>
|
||||||
|
<p><strong>包括:</strong>您通过本政策公示联系方式提交给我们的信息。</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于用户与我们联系,提升用户体验</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>联系我们</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> </p>
|
||||||
|
<p>(二)您可以选择授权提供个人信息的场景</p>
|
||||||
|
<p>您可以通过访问您所依托的移动应用程序(微信或种草短剧 APP)的隐私设置逐项查看您上系统权限的开启状态,并可以决定设置权限的开启或关闭(如适用)。请您注意,您开启这些权限后且在种草短剧内授权即代表您授权我们可以收集和使用这些个人信息来实现对应的功能,您关闭权限即代表您取消了授权,则我们将不再继续收集和使用您的相关个人信息,也无法为您提供上述与这些授权所对应的功能。您关闭权限的决定不会影响此前基于您的授权所进行的个人信息的处理。</p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="189">
|
||||||
|
<p><strong>收集的权限</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p><strong>权限与获取信息描述</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p><strong>目的/</strong><strong>用途</strong></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="189">
|
||||||
|
<p>相册权限</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>允许使用相册</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>用于保存或上传图片</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="189">
|
||||||
|
<p>定位权限</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>允许使用定位</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>用于分析用户地域标签分配业务</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong>(三)征得同意的例外</strong></p>
|
||||||
|
<p>您应充分知晓,以下情形中,我们收集、使用个人信息无需征得您的授权同意:</p>
|
||||||
|
<p>1.与国家安全、国防安全有关的;</p>
|
||||||
|
<p>2.为订立、履行个人作为一方当事人的合同所必需;</p>
|
||||||
|
<p>3.为履行法定职责或者法定义务所必需;</p>
|
||||||
|
<p>4.为应对突发公共卫生事件,或者紧急情况下为保护自然人的生命健康和财产安全所必需;</p>
|
||||||
|
<p>5.为公共利益实施新闻报道、舆论监督等行为,在合理的范围内处理个人信息;</p>
|
||||||
|
<p>6.依照本法规定在合理的范围内处理个人自行公开或者其他已经合法公开的个人信息;</p>
|
||||||
|
<p>7.用于维护所提供的服务的安全稳定运行所必需的,例如发现、处置产品与/或服务的故障;</p>
|
||||||
|
<p>8.收集将个人信息匿名化处理后形成的数据;</p>
|
||||||
|
<p>9.我们因重组、分拆、调整等主体变更导致向继受者提供或者转移个人信息的情形;</p>
|
||||||
|
<p>10.法律、行政法规规定的其他情形。</p>
|
||||||
|
<p><strong>(四)个人信息使用规则</strong></p>
|
||||||
|
<p>1.我们会根据本《隐私权政策》所述,为实现我们的产品与/或服务功能而对所收集的个人信息进行使用。</p>
|
||||||
|
<p>2.请您了解并同意,对于您在使用我们的产品与/或服务时所提供的所有个人信息,除非您删除或通过系统设置拒绝我们收集,否则将被视为在您使用我们的产品与/或服务期间持续授权同意我们使用。</p>
|
||||||
|
<p>3.当我们要将您的个人信息用于本隐私声明未载明的其它用途时,或基于特定目的收集而来的个人信息用于其他目的时,会事先征求您的明示同意。请您理解,我们向您提供的产品与/或服务将不断更新变化。如果您选择使用本隐私声明中尚未列明的其他产品与/或服务时,我们会在收集您的个人信息前通过协议、页面提示等方式向您详细说明信息收集的目的、方式、范围并征求您的同意。若您不同意提供前述信息,您将无法使用该项产品与/或服务,但不影响您使用现有产品与/或服务。</p>
|
||||||
|
<p><strong>二、我们如何共享、转让、公开披露您的个人信息</strong></p>
|
||||||
|
<p><strong>(一)共享</strong></p>
|
||||||
|
<p>我们不会与非服务提供者以外的公司、组织和个人共享您的个人信息,但以下情况除外:</p>
|
||||||
|
<p>1.在获取明确同意情况下共享:获得您的明确同意后,我们会与其他方共享您的个人信息。例如,如果我们委托第三方向您提供产品或服务时,我们会在征得您同意后将上述信息共享给第三方,如果您拒绝提供此类信息,我们将无法完成相关交付服务。</p>
|
||||||
|
<p>2.在法定情形下共享:我们会根据法律法规规定、诉讼争议解决需要,或按行政、司法机关依法提出的要求,对外共享您的个人信息。</p>
|
||||||
|
<p>3.我们可能会委托授权合作伙伴为您提供某些服务或代表我们履行职能,在此之前我们会和他们通过不限于签订协议的方式约定双方的权利和义务。我们仅会出于合法、正当、必要、特定、明确的目的处理您的信息,授权合作伙伴只能接触到为其履行职责所需信息,且不能将此信息用于任何其他目的。</p>
|
||||||
|
<p>4.为处理您与他人的纠纷或争议。</p>
|
||||||
|
<p><strong>(二)转让</strong></p>
|
||||||
|
<p>我们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:</p>
|
||||||
|
<p>1.事先获得您明确的同意或授权;</p>
|
||||||
|
<p>2.根据适用的法律法规、法律程序的要求、强制性的行政或司法要求所必须的情况进行提供;</p>
|
||||||
|
<p>3.符合与您签署的相关协议(包括在线签署的电子协议以及相应的平台规则)或其他的法律文件约定所提供;</p>
|
||||||
|
<p>4.随着我们业务的发展,我们及我们的关联方有可能进行合并、收购、资产转让或类似的交易,<strong>如涉及个人信息的转让,我们会要求受让您个人信息的公司、组织继续接受本隐私声明的约束,否则</strong><strong>,</strong><strong>我们将要求该公司、组织重新征求您的授权同意。</strong></p>
|
||||||
|
<p><strong>(三)公开披露</strong></p>
|
||||||
|
<p>我们仅会在以下情况,公开披露您的个人信息:</p>
|
||||||
|
<p>1.获得您明确同意或基于您的主动选择,我们会公开披露您的个人信息;</p>
|
||||||
|
<p>2.根据法律、法规的要求、强制性的行政执法或司法要求所必须提供您个人信息的情况下,我们会依据所要求的个人信息类型和披露方式公开披露您的个人信息。在符合法律法规的前提下,当我们收到上述披露信息的请求时,我们会要求必须出具与之相应的法律文件。</p>
|
||||||
|
<p>3.对违规账号、欺诈行为进行处罚公告时,我们会披露相关账号的必要信息。</p>
|
||||||
|
<p><strong>(四)共享、转让、公开披露个人信息时事先征得授权同意的例外</strong></p>
|
||||||
|
<p>以下情形中,共享、转让、公开披露您的个人信息无需事先征得您的授权同意:</p>
|
||||||
|
<p>1.与我们履行法律法规规定的义务相关的;</p>
|
||||||
|
<p>2.根据法律法规的规定或行政、司法机构、国家部门等有权机关的要求依法提供的;</p>
|
||||||
|
<p>3.出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;</p>
|
||||||
|
<p>4.您自行向社会公众公开的个人信息;</p>
|
||||||
|
<p>5.与国家安全、国防安全直接相关的;</p>
|
||||||
|
<p>6.从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。</p>
|
||||||
|
<p>根据法律规定,共享、转让经去标识化处理的个人信息,且确保数据接收方无法复原并重新识别个人信息主体的,不属于个人信息的对外共享、转让及公开披露行为,对此类数据的共享、转让、公开披露、保存及处理将无需另行向您通知并征得您的同意。</p>
|
||||||
|
<p><strong>三、我们如何存储和保护您的个人信息</strong></p>
|
||||||
|
<p><strong>(一)存储您的个人信息</strong></p>
|
||||||
|
<p>1.存储地域范围</p>
|
||||||
|
<p>我们在中华人民共和国境内收集和产生的个人信息将存储在中华人民共和国境内,但以下情形除外:(1)法律法规有明确规定的;(2)依法征得您的同意。在上述除外情形中,我们会要求数据接收方按照本政策以及其他相关的安全保密措施来处理个人信息。</p>
|
||||||
|
<p>2.存储期限</p>
|
||||||
|
<p>除法律法规规定、获得您的同意或双方另有约定外,我们通常仅在实现本政策所述目的所必需的期限内保留您的个人信息。</p>
|
||||||
|
<p>3.终止服务</p>
|
||||||
|
<p>如果我们终止服务或运营,我们会至少提前三十日向您通知,并在终止服务或运营后对您的个人信息进行删除。</p>
|
||||||
|
<p><strong>(二)保护您个人信息的措施</strong></p>
|
||||||
|
<p>1.我们非常重视个人信息安全,并采取符合行业标准的安全技术措施保护您提供的个人信息的安全。</p>
|
||||||
|
<p>2.我们通过建立专门的管理制度、流程、组织等管理措施以保障信息的安全。例如,我们使用用户信息集中管理系统,我们只允许有必要接触用户信息的工作人员访问该系统查询和管理客户信息。我们严格设定访问用户信息的权限分级,同时要求可能接触到您个人信息的所有人员履行相应的保密义务。我们还不时对工作人员培训相关法律法规及隐私安全准则,强化宣导安全意识。</p>
|
||||||
|
<p>3.若发生个人信息泄露等安全事件,我们会启动应急预案,阻止安全事件扩大。我们会及时将事件的基本情况、处置措施、降低风险建议等以电话、推送通知等方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。</p>
|
||||||
|
<p><strong>四、您如何管理个人信息</strong></p>
|
||||||
|
<p><strong>(一)查询、更正和补充您的个人信息</strong></p>
|
||||||
|
<p>您有权查询、更正或补充您的信息。若您无法查看或更正的信息,请通过本政策公示的联系方式协助您查询、更正或补充。</p>
|
||||||
|
<p><strong>(二)删除您的个人信息</strong></p>
|
||||||
|
<p>在以下情形中,您可以向我们提出删除个人信息的请求:</p>
|
||||||
|
<p>1.如果我们处理个人信息的行为违反法律法规;</p>
|
||||||
|
<p>2.如果我们收集、使用您的个人信息,却未征得您的明确同意;</p>
|
||||||
|
<p>3.如果我们处理个人信息的行为严重违反了与您的约定;</p>
|
||||||
|
<p>4.如果您不再使用我们的产品或服务;</p>
|
||||||
|
<p>5.如果我们停止为您提供产品或服务。</p>
|
||||||
|
<p>当您或我们协助您删除相关信息后,因为适用的法律和安全技术,我们可能无法立即从备份系统中删除相应的信息,我们将安全地存储您的个人信息并将其与任何进一步处理隔离,直到备份可以清除或实现匿名。</p>
|
||||||
|
<p><strong>(三)改变您授权同意的范围或撤回您的授权</strong></p>
|
||||||
|
<p>请您理解,每个业务功能需要一些基本的个人信息才能得以完成,当您撤回同意或授权后,我们无法继续为您提供撤回同意或授权所对应的服务,也不再处理您相应的个人信息。但您撤回同意或授权的决定,不会影响此前基于您的授权而开展的个人信息处理。</p>
|
||||||
|
<p><strong>(四)注销帐号</strong></p>
|
||||||
|
<p><strong>您可以通过本政策“</strong><strong>如何联系我们”</strong><strong>部分提供的联系方式注销您的账号。请注意,在您注销账号后,我们将根据法律规定删除或匿名化处理您的个人信息,请谨慎进行账号注销操作。</strong></p>
|
||||||
|
<p><strong>(五)响应您的请求</strong></p>
|
||||||
|
<p>为保障安全,您可能需要提供书面请求,或以其他方式证明您的身份。我们将会先要求您验证自己的身份,然后再处理您的请求。我们将在【15】天内做出答复。</p>
|
||||||
|
<p>对于您合理的请求,我们原则上不收取费用,但对多次重复、超出合理限度的请求,我们将酌情收取一定费用。对于与您的身份不直接关联的信息、无端重复信息,或者需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者不切实际的请求,我们可能会予以拒绝。</p>
|
||||||
|
<p>在以下情形中,按照法律法规要求,我们将无法响应您的请求:</p>
|
||||||
|
<p>1.与我们履行法律法规规定的义务相关的;</p>
|
||||||
|
<p>2.与国家安全、国防安全有关的;</p>
|
||||||
|
<p>3.与公共安全、公共卫生、重大公共利益有关的;</p>
|
||||||
|
<p>4.与犯罪侦查、起诉、审判和执行判决等有关的;</p>
|
||||||
|
<p>5.有充分证据表明个人信息主体存在主观恶意或滥用权利的;</p>
|
||||||
|
<p>6.响应您的请求将导致您或其他个人、组织的合法权益受到严重损害的;</p>
|
||||||
|
<p>7.涉及商业秘密的。</p>
|
||||||
|
<p><strong>五、未成年人的个人信息保护</strong></p>
|
||||||
|
<p>(一)本政策所指的未成年人是指不满18周岁的个人,如果没有父母或监护人的同意,未成年人不得创建自己的用户帐户。如您为未成年人的,建议您请您的父母或监护人仔细阅读本隐私权政策,并在征得您的父母或监护人同意的前提下使用我们的服务或向我们提供信息。</p>
|
||||||
|
<p>(二)对于经父母或监护人同意使用我们的产品或服务而收集未成年人个人信息的情况,我们只会在法律法规允许、父母或监护人明确同意或者保护未成年人所必要的情况下使用、共享、转让或披露此信息。</p>
|
||||||
|
<p>(三)如果我们发现自己在未事先获得可证实的父母同意的情况下收集了未成年人的个人信息,则会设法尽快删除相关数据。</p>
|
||||||
|
<p><strong>六、通知和修订</strong></p>
|
||||||
|
<p>(一)为给您提供更好的服务以及随着种草短剧业务的发展,我们的隐私权政策可能变更。但未经您明确同意,我们不会限制您按照本隐私权政策所应享有的权利。我们会在生效前通过公告或以其他适当方式提醒您对隐私权政策所做的任何变更。如您继续使用我们的服务,表示同意接受修订后的本隐私政策的内容。</p>
|
||||||
|
<p>(二)本政策所指的重大变更包括但不限于:</p>
|
||||||
|
<p>1.我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式等;</p>
|
||||||
|
<p>2.我们在组织架构等方面发生重大变化。如并购重组等引起的信息控制者变更等;</p>
|
||||||
|
<p>3.个人信息共享、转让或公开披露的主要对象发生变化;</p>
|
||||||
|
<p>4.您参与个人信息处理方面的权利及其行使方式发生重大变化;</p>
|
||||||
|
<p>5.我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化;</p>
|
||||||
|
<p>6.个人信息安全影响评估报告表明存在高风险。</p>
|
||||||
|
<p>(三)您可以通过“【<strong>我的</strong><strong>-</strong><strong>隐私权政策</strong>】”中查看本政策的最新版本。</p>
|
||||||
|
<p><strong>七、如何联系我们</strong></p>
|
||||||
|
<p>(一)本政策提及的可能需要与我们取得联系的情况下,或您对本政策内容有任何疑问、意见或建议的,您可以通过以下方式联系我们:</p>
|
||||||
|
<p>①小程序页面扫码添加客服企业微信</p>
|
||||||
|
<p>②电子邮件:【13951762324@163.com】</p>
|
||||||
|
<p>③联系地址:【深圳湾科技生态园9栋A1座3102室】</p>
|
||||||
|
<p>(二) 一般情况下,我们将在收到您反馈并验证您的身份后【十五】天内回复。如果您对我们的回复不满意,特别是您认为我们的个人信息处理行为损害了您的合法权益,您可以向网信、电信、公安及工商等监管部门进行投诉或举报,亦或向被告住所地有管辖权的法院提起诉讼来寻求解决方案。</p></div></div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
padding: 20upx;
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
border: 0.02667rem solid #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<div class="box" data-v-c44c8a1a=""><div class="text" data-v-c44c8a1a=""><p style="text-align: center;"><strong>【种草短剧】用户协议</strong></p>
|
||||||
|
<p style="text-align: right;">发布日期:2023年 05月 19日</p>
|
||||||
|
<p>欢迎您来到并使用种草短剧平台服务!</p>
|
||||||
|
<p> </p>
|
||||||
|
<p>本协议由用户(以下或称“您”)与种草短剧平台经营者(以下或称“种草短剧”,详见定义条款)共同签订,种草短剧平台经营者依据本协议为您提供服务。</p>
|
||||||
|
<p><strong>请您在访问或使用前,仔细阅读本协议中所有内容,尤其是种草短剧</strong><strong>免责条款、对您的权利限制条款以及争议解决条款等重要条款内容,本协议中会以加粗显示方式提示您注意,您应重点阅读。</strong>如您对协议有任何疑问,可向种草短剧平台客服咨询。</p>
|
||||||
|
<p>您有权选择同意或不同意本协议。当您按照注册页面提示填写信息、阅读并同意本协议且完成全部注册程序后,或使用第三方账号登录种草短剧平台,即视为您已充分阅读、理解并接受本协议的全部内容,并与种草短剧达成一致,成为种草短剧平台“用户”。阅读本协议的过程中,如果您不同意本协议或其中任何条款约定,您应立即停止注册程序并停止使用种草短剧平台服务。</p>
|
||||||
|
<p><strong><em><u>请您在决定登录、注册或使用种草短剧</u></em></strong><strong><em><u>平台服务前再次确认您已知悉并完全理解本协议的所有内容。如果您未满16</u></em></strong><strong><em><u>周岁,或已满16</u></em></strong><strong><em><u>周岁未满18</u></em></strong><strong><em><u>周岁且不能以自己的劳动收入作为主要收入来源的,请在法定监护人的陪同下阅读本协议,请务必在家长和其他法定监护人的陪同下阅读本协议,并在进行注册、使用种草短剧</u></em></strong><strong><em><u>平台的其他任何服务前,应事先征得您的家长和其他法定监护人的同意。</u></em></strong></p>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong>1</strong><strong>、 </strong><strong>定义</strong></p>
|
||||||
|
<p>1.1种草短剧平台的经营者/种草短剧:指实际经营种草短剧平台的法律主体,现为杭州亮宇网络科技有限公司。<strong><u>本协议项下,麻雀</u></strong><strong><u>MATRIX</u></strong><strong><u>平台经营者可能根据种草短剧</u></strong><strong><u>平台的业务调整而发生变更,具体以种草短剧</u></strong><strong><u>平台公示的信息为准。种草短剧</u></strong><strong><u>平台经营者的变更不会影响本协议项下约定的各项权利义务。您有权选择同意或不同意本协议项下种草短剧</u></strong><strong><u>主体的变更,具体适用本协议第2.2</u></strong><strong><u>条关于协议变更的约定。</u></strong></p>
|
||||||
|
<p>1.2 种草短剧平台服务:指种草短剧基于互联网,以微信小程序、app等形态(包括未来技术发展出现的新的服务形态)向您提供的各项服务,关于“种草短剧”及其服务的解释权归种草短剧所有。</p>
|
||||||
|
<p>1.3 种草短剧平台规则:包括所有种草短剧已经发布及后续可能发布、修订的各类规则、规范、解读、实施细则、通知、公告等。</p>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong>2</strong><strong>、 </strong><strong>协议范围及变更</strong></p>
|
||||||
|
<p>2.1协议范围:由于互联网高速发展,您与种草短剧签署的本协议列明的条款并不能完整罗列并覆盖您与种草短剧所有权利与义务,现有的约定也不能保证完全符合未来发展的需求。同时,种草短剧平台隐私权政策、种草短剧平台规则均为本协议的补充协议,与本协议不可分割且具有同等法律效力。如您使用种草短剧平台服务,视为您同意上述补充协议。</p>
|
||||||
|
<p><em><u>2.2 </u></em><strong><em><u>协议变更:种草短剧</u></em></strong><strong><em><u>可根据国家法律法规变化及维护交易秩序需要,种草短剧</u></em></strong><strong><em><u>有权根据“种草短剧</u></em></strong><strong><em><u>”及其服务的调整对本协议内容进行修改、更新、废止,变更后的协议将在相关页面或其他合适的方式公布。用户如果不同意变更后的协议,应放弃使用“种草短剧</u></em></strong><strong><em><u>”或相关服务;如果用户选择在协议变更后继续访问或使用“种草短剧</u></em></strong><strong><em><u>”,则视为用户接受已生效的变更事项。</u></em></strong></p>
|
||||||
|
<p><strong>3</strong><strong>、 </strong><strong>用户账户登录与使用</strong></p>
|
||||||
|
<p><strong>3.1 </strong><strong>账户登录</strong></p>
|
||||||
|
<p><strong>用户资格</strong>:您确认,在您开始注册/登录程序使用种草短剧平台服务前,您应当具备中华人民共和国法律规定的与您行为相适应的民事行为能力。若您不具备前述与您行为相适应的民事行为能力,则您及您的监护人应依照法律规定承担因此而导致的一切后果。</p>
|
||||||
|
<p><strong>信息真实:</strong>在使用种草短剧平台服务时,您应当按种草短剧平台页面的提示准确完整地提供您的信息。如果您提供的信息不合法、不真实、不准确、不详尽的,您需承担因此引起的相应责任及后果,并且种草短剧保留终止您使用种草短剧各项服务的权利。您了解并同意,您有义务保持您提供信息的真实性及有效性。</p>
|
||||||
|
<p><strong>真实身份:</strong>因国家法律法规、监管要求,您有可能需要在使用该等服务的特定环节中填写真实的个人信息,并需通过相关验证流程后方可使用服务,如您填写的信息不完整、不真实或未通过验证,将导致您无法使用该服务、损害自身、他人利益或造成其他不利后果,该等后果将由您自行承担。</p>
|
||||||
|
<p><strong>更新维护:</strong>您应当及时更新您提供的信息,在法律有明确规定要求种草短剧作为平台服务提供者必须对部分用户的信息进行核实的情况下,种草短剧将依法不时地对您的信息进行检查核实,您应当配合提供最新、真实、完整、有效的信息。</p>
|
||||||
|
<p>如种草短剧按您最后一次提供的信息与您联系未果、您未按种草短剧的要求及时提供信息、您提供的信息存在明显不实或行政司法机关核实您提供的信息无效的,您将承担因此对您自身、他人及种草短剧造成的全部损失与不利后果。种草短剧可向您发出询问或要求整改的通知,并要求您进行重新认证,直至中止、终止对您提供部分或全部种草短剧平台服务,种草短剧对此不承担责任。</p>
|
||||||
|
<p><strong>用户名的合法性:</strong>您设置的种草短剧平台用户名(昵称)不得违反国家法律法规及种草短剧平台规则关于用户名(昵称)的管理规定,不得包含违法、涉嫌侵犯他人权利、有违公序良俗或干扰种草短剧平台运营秩序等相关信息,否则种草短剧有权向您发出要求修改的通知,直至中止、终止对您提供部分或全部种草短剧平台服务,种草短剧对此不承担责任。</p>
|
||||||
|
<p><strong>3.2 </strong><strong>账户说明</strong></p>
|
||||||
|
<p><strong>账户获得:</strong>当您按照登录页面提示填写信息、阅读并同意本协议且完成全部登录程序后,您可成为种草短剧平台用户。</p>
|
||||||
|
<p><strong><em><u>账户登录与使用:</u></em></strong><strong><em><u>您有权使用您确认的手机号码或第三方账号登录种草短剧</u></em></strong><strong><em><u>平台。由于您的种草短剧</u></em></strong><strong><em><u>平台账户关联您的个人信息及种草短剧</u></em></strong><strong><em><u>平台商业信息,您的种草短剧</u></em></strong><strong><em><u>平台账户仅限您本人使用。未经种草短剧</u></em></strong><strong><em><u>同意,您直接或间接授权第三方使用您种草短剧</u></em></strong><strong><em><u>平台账户或获取您账户项下信息的行为无效。如根据种草短剧</u></em></strong><strong><em><u>平台规则中约定的违约认定程序及标准判断您账户的使用可能危及您的账户安全及/</u></em></strong><strong><em><u>或种草短剧</u></em></strong><strong><em><u>平台信息安全的,种草短剧</u></em></strong><strong><em><u>平台可拒绝提供相应服务或终止本协议、冻结或注销账户,并可要求您承担因此产生的一切责任和损失。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>限制冻结:</u></em></strong><strong><em><u>您知悉并同意,在符合法律法规的规定,或经国家机关要求的前提下,种草短剧</u></em></strong><strong><em><u>平台有权对您的注册账户进行限制或冻结,在该等情况下,您可能无法继续登陆或使用您的账户。</u></em></strong></p>
|
||||||
|
<p><strong>3.3 </strong><strong>账户安全规范</strong></p>
|
||||||
|
<p>账户安全保管义务:您的账户为您自行设置并由您保管。凡经您的账号和密码成功登录使用种草短剧平台,即视为您的使用行为。因此,建议您务必保管好您的账户,并确保您在每个上网时段结束时退出登录并以正确步骤离开种草短剧平台。您知悉并同意,如您在账户信息的保管上、相关上网设备的网络安全维护上存在任何过失,或是因您主动泄露或因您遭受他人攻击、诈骗等行为导致账户丢失、泄露,您应对此产生的任何损失和后果负责,种草短剧对此不负任何责任,您应通过司法、行政等救济途径向侵权行为人追偿,如种草短剧因此产生相关支出,种草短剧将有权向您追偿。</p>
|
||||||
|
<p><strong><em><u>账户行为责任自负:除种草短剧</u></em></strong><strong><em><u>存在过错外,您应对您账户项下的所有行为结果(包括但不限于在线签署各类协议、履行义务、披露信息等)负责,通过您的账户所发生的上述各项行为将视为您本人的真实意思表示。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>您通过账户在接受种草短剧</u></em></strong><strong><em><u>平台的各项服务中所上传、发送的任何内容都应具有合法来源,如相关内容涉及任何第三方的合法权益,应事先获得相应的许可。如种草短剧</u></em></strong><strong><em><u>平台收到涉及您的相关举报或投诉,种草短剧</u></em></strong><strong><em><u>平台可采取相关法律法规所要求或允许的方式,向相关争议方、相关部门提供包括账户在内的必要的信息,以便解决纠纷争议,保护正当权利人的合法权益。</u></em></strong></p>
|
||||||
|
<p>日常维护须知:如发现任何未经授权使用您账户登录种草短剧平台或其他可能导致您账户遭窃、遗失的情况,建议您立即通知种草短剧。您理解种草短剧对您的任何请求采取行动均需要合理时间,且种草短剧应您请求而采取的行动可能无法避免或阻止侵害后果的形成或扩大,除种草短剧存在法定过错外,种草短剧不承担责任。</p>
|
||||||
|
<p>4、 种草短剧平台服务及规范</p>
|
||||||
|
<p><strong>4.1 </strong><strong>任务详情:</strong>当您选择变现项目时,您可以在“首页”中查看各变现项目的详情。</p>
|
||||||
|
<p><strong>4.2 </strong><strong>数据:</strong>当您选择、完成变现项目任务时,您可以在“数据”中查看您的数据统计及预估收益,预估收益仅供参考,具体以您实际收到的为准。</p>
|
||||||
|
<p>4.3<strong>费用结算:</strong>若您通过种草短剧领取变现项目任务并按照要求履行完毕,种草短剧或种草短剧委托的第三方将向您支付相应费用,种草短剧亦有权通过各变现项目对应的推广平台分佣结算功能实现线上分佣。结算过程中,若需您提供必要协助(包括但不限于推广平台线上分佣所需的资料提交等),您应无条件配合,否则种草短剧有权不予结算且无需承担任何违约责任。</p>
|
||||||
|
<p><strong><em><u>提现规则:部分合作费您可在种草短剧</u></em></strong><strong><em><u>平台申请提现,具体提现规则(包括但不限于提现限额、次数、提现日期、支付周期等)以提现页面规定(包括但不限于协议、提现功能设置)为准。平台可根据业务发展需要、提现策略变更等因素调整提现规则,您对此表示理解且接受。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>若您作为种草短剧</u></em></strong><strong><em><u>合作方(代理</u></em></strong><strong><em><u>)引进的创作者,种草短剧</u></em></strong><strong><em><u>已根据其与合作方的合作协议,自行或通过指定的第三方与合作方完成费用结算的,则无需向您支付任何费用。您与合作方之间有关费用结算产生的任何争议,均与种草短剧</u></em></strong><strong><em><u>无涉。</u></em></strong></p>
|
||||||
|
<p><strong>4.4</strong><strong>税费约定:</strong>您通过种草短剧产生的所有收益,均应自行承担税费并依法履行缴税义务。</p>
|
||||||
|
<p><strong><em><u>4.5 </u></em></strong><strong><em><u>责任限制</u></em></strong></p>
|
||||||
|
<p><strong><em><u>4.5.1 </u></em></strong><strong><em><u>不可抗力:不可抗力是指不能预见、不能克服并不能避免的客观事件,包括地震、台风、水灾、火灾、战争、国际或国内运输中断、流行病、罢工,以及根据中国法律或一般商业惯例认作不可抗力的其他事件。如果发生不可抗力事件,影响一方履行其在本合同项下的义务,则在不可抗力造成的延误期内导致的合同履行障碍、履行瑕疵、履行延后等情形,而不视为违约。宣称发生不可抗力的一方应迅速书面通知其他对方,并在其后的15</u></em></strong><strong><em><u>天内提供证明不可抗力发生及其持续时间的足够证据。如果发生不可抗力事件,双方应立即互相协商,以找到公平的解决办法,并且应尽一切合理努力将不可抗力的影响减少到最低限度。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>4.5.2 </u></em></strong><strong><em><u>第三方原因:种草短剧</u></em></strong><strong><em><u>依照法律规定履行基础保障义务的前提下,因电力供应故障、通讯网络故障等公共服务因素或黑客攻击、计算机病毒侵入或发作等第三方因素导致种草短剧</u></em></strong><strong><em><u>无法提供相关服务或提供服务有瑕疵或迟延的,种草短剧</u></em></strong><strong><em><u>公司应及时向您进行通知、采取紧急措施避免扩大损失。如种草短剧</u></em></strong><strong><em><u>未尽通知义务或处理存在过错导致扩大化损失的,应就该部分损失承担责任。 </u></em></strong></p>
|
||||||
|
<p><strong><em><u>4.5.3 </u></em></strong><strong><em><u>非担保:除非另有明确书面说明,在符合法律法规规定的情况下,种草短剧</u></em></strong><strong><em><u>不对种草短剧</u></em></strong><strong><em><u>平台上的信息、内容、材料、产品或服务做任何形式的明示或默示的声明或担保。</u></em></strong></p>
|
||||||
|
<p><strong>5</strong><strong>、 </strong><strong>用户信息的保护及授权</strong></p>
|
||||||
|
<p>5.1 【授权收集】在您使用种草短剧提供的服务时,您同意种草短剧收集、存储、使用、披露和保护您的个人信息(即能够独立或与其他信息结合后识别用户身份的信息,包括但不限于姓名、手机号、收款银行账号、公民身份号码等)。</p>
|
||||||
|
<p><strong><em><u>5.2 </u></em></strong><strong><em><u>【信息保护】尊重和保护用户的个人信息是种草短剧</u></em></strong><strong><em><u>的一项基本政策。种草短剧</u></em></strong><strong><em><u>将按照本协议及《隐私权政策》的规定收集、使用、储存、保护和提供您的个人信息。本协议对个人信息保护相关内容未作明确规定的,请参见《隐私权政策》。</u></em></strong></p>
|
||||||
|
<p><strong>6</strong><strong>、 </strong><strong>用户行为规范</strong></p>
|
||||||
|
<p>6.1 您知悉并承诺,在使用种草短剧所提供的服务的过程中,您应遵守相关法律法规,不应从事或协助、教唆他人从事违反法律法规的规定、影响正常服务提供或损害他人合法利益的行为,包括但不限于:</p>
|
||||||
|
<p>(1)利用种草短剧平台或相关服务从事违反国家法律法规禁止性规定的行为;</p>
|
||||||
|
<p>(2)因对种草短剧平台相关服务的使用行为导致种草短剧卷入政治和公共事件;</p>
|
||||||
|
<p>(3)入侵种草短剧平台计算机信息系统,或从事危害计算机信息网络安全的活动;</p>
|
||||||
|
<p>(4)擅自复制和使用网络上未公开和未授权的文件。除相关著作权人明示同意,不应在网络中擅自破解、传播、下载或复制第三人享有著作权的软件或进行其他任何侵害他人知识产权的活动;</p>
|
||||||
|
<p>(5)盗取他人种草短剧账户、银行账号等信息或盗取他人种草短剧账户中的资产中的资产;</p>
|
||||||
|
<p>(6)其他干扰种草短剧平台正常运转或正常交易秩序、违反公平或诚实信用原则的行为;</p>
|
||||||
|
<p>(7)使用欺骗手段及(或)利用系统bug、漏洞等虚构履约状态谋取利益。</p>
|
||||||
|
<p>6.2 【信息发布】用户使用种草短剧的服务时必须遵守有关法律法规,不得在种草短剧上或者利用种草短剧的服务制作、复制、发布、传播以下信息:</p>
|
||||||
|
<p>(1)违反国家法律法规禁止性规定的;</p>
|
||||||
|
<p>(2)政治宣传、封建迷信、淫秽、色情、赌博、暴力、恐怖或者教唆犯罪的;</p>
|
||||||
|
<p>(3)欺诈、虚假、不准确或存在误导性的;</p>
|
||||||
|
<p>(4)侵犯他人知识产权或涉及第三方商业秘密及其他专有权利的;</p>
|
||||||
|
<p>(5)侮辱、诽谤、恐吓、涉及他人隐私等侵害他人合法权益的;</p>
|
||||||
|
<p>(6)存在可能破坏、篡改、删除、影响种草短剧平台任何系统正常运行或未经授权秘密获取种草短剧平台及其他用户的数据、个人资料的病毒、木马、爬虫等恶意软件、程序代码的;</p>
|
||||||
|
<p>(7)其他违背社会公共利益或公共道德或依据相关种草短剧平台协议、规则的规定不适合在种草短剧平台上发布的。</p>
|
||||||
|
<p><strong>6.3 </strong><strong>软件使用及规范</strong></p>
|
||||||
|
<p>【软件使用】如果您从未经种草短剧授权的第三方获取软件或与该软件名称相同的安装程序,种草短剧无法保证该软件能够正常使用,由此造成的相关损失,种草短剧不予负责。</p>
|
||||||
|
<p>基于改善用户体验、修复漏洞、保障安全性等因素考虑,种草短剧将不时对软件进行更新,请您及时核对并更新最新版本。</p>
|
||||||
|
<p>除非法律允许或种草短剧书面许可,您使用种草短剧平台过程中不得从事下列任一行为:</p>
|
||||||
|
<p>(1)删除、编辑或遮挡软件及其副本上关于著作权、商标或其他权利标识或标记的信息;</p>
|
||||||
|
<p>(2)对软件进行反向工程、反向汇编、反向编译,或者以其他方式挖掘、提取软件的源代码;</p>
|
||||||
|
<p>(3)对种草短剧拥有知识产权的内容进行使用、出租、出借、出售、复制、修改、链接、转载、汇编、发表、出版、建立镜像站点等;</p>
|
||||||
|
<p>(4)对软件或者软件运行过程中释放到任何终端内存中的数据、软件运行过程中客户端与服务器端的交互数据,以及软件运行所必需的系统数据,进行复制、修改、增加、删除、挂接运行或创作任何衍生作品,形式包括但不限于使用插件、外挂或非经种草短剧授权的第三方工具/服务接入软件和相关系统;</p>
|
||||||
|
<p>(5)通过修改或伪造软件运行中的指令、数据,增加、删减、变动软件的功能或运行效果,或者将用于上述用途的软件、方法进行运营或向公众传播,无论这些行为是否为商业目的;</p>
|
||||||
|
<p>(6)通过非种草短剧开发、授权的第三方软件、插件、外挂、系统,登录或使用种草短剧平台及服务,或制作、发布、传播上述工具;</p>
|
||||||
|
<p>(7)自行或者授权他人、第三方软件对本软件及其组件、模块、数据进行干扰。</p>
|
||||||
|
<p><strong>7</strong><strong>、 </strong><strong>所有权及知识产权</strong></p>
|
||||||
|
<p>7.1 种草短剧软件及相关服务中提供的任何内容(包括但不限于软件、技术、程序、网页、文字、图片、图像、音频、视频、图表、版面设计、电子文档等)的知识产权属于种草短剧或(及)关联公司所有。本公司提供本服务时所依托的软件的著作权、专利权及其他知识产权均归公司所有。未经本公司事先书面许可,您承诺不应且不应允许或协助任何人以任何形式(包括但不限于通过任何机器人、蜘蛛等程序或设备)监视、复制、传播、展示、镜像、上载、下载“种草短剧”软件及相关服务中的内容或创造相关衍生作品。未经本公司事先书面同意,您不得擅自使用、掩盖或更改本公司的版权声明、商标或其他权利声明(若有),不得将本公司的商标以任何方式展示使用或作其他处理,也不得实施向他人明示或暗示有权展示、使用、或其他有权处理该些标识的行为。由于您违反本协议使用本公司上述商标、标识等给本公司或他人造成损失的,由您承担全部法律责任。</p>
|
||||||
|
<p><strong><em><u>7.2</u></em></strong><strong><em><u>种草短剧</u></em></strong><strong><em><u>为履行本协议而向您提供的所有素材(包括但不限于视频、文字等,以种草短剧</u></em></strong><strong><em><u>实际提供的为准),其所有知识产权归种草短剧</u></em></strong><strong><em><u>或原权利人所有。您仅可以为履行本协议之目的按种草短剧</u></em></strong><strong><em><u>认可的内容、方式和范围等使用上述素材,未经种草短剧</u></em></strong><strong><em><u>许可,不得以任何形式允许(包括但不限于转让、授权)第三方使用。否则由此导致的一切责任与后果由您承担,如因此给种草短剧</u></em></strong><strong><em><u>、种草短剧</u></em></strong><strong><em><u>合作方(如合作艺人、达人等)等造成任何损失的,您应负责全额赔偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>7.3 </u></em></strong><strong><em><u>您理解并同意,若后续您在使用种草短剧</u></em></strong><strong><em><u>平台提供的服务时需要上传、提交或存储的内容(包括但不限于文字、图片、视频、音频、动画等),您需保证签署内容均由您原创或已获合法授权,您的上述操作行为不会侵犯他人的知识产权或其他合法权益。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>您同意,因您通过种草短剧</u></em></strong><strong><em><u>平台上操作的任何内容导致的知识产权侵权问题,您将承担全部责任;如种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司因第三方知识产权维权而产生损失,您应全额赔偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>7.4</u></em></strong><strong><em><u>您知悉、理解并同意,您一旦接受本服务协议,即表明您主动将上述用户生成内容的非专属、可转让的财产性权利,如著作权(包括但不限于:复制权、发行权、出租权、展览权、表演权、放映权、广播权、信息网络传播权、摄制权、改编权、翻译权、汇编权以及应当由著作权人享有的其他可转让权利),在全世界范围内永久、免费且不可撤销地授权给种草短剧</u></em></strong><strong><em><u>及其关联公司,种草短剧</u></em></strong><strong><em><u>及其关联公司可基于该等授权使用上述内容(包括但不限于用于商业用途)或向第三方自主进行任何必要的转授权。如该等内容并非您原创,则您承诺您已获得合法授权对种草短剧</u></em></strong><strong><em><u>及其关联公司进行前述授权。该等授权、转授权的使用场景包括但不限于当前或其他任何网站、应用程序、产品或移动终端设备等,且种草短剧</u></em></strong><strong><em><u>及其关联公司或种草短剧</u></em></strong><strong><em><u>及其关联公司所授权许可的第三方可通过对上述授权内容进行修改、复制、改编、翻译、汇编或制作,形成衍生产品。在不违反相关法律法规的强制性规定、尊重相关原始授权内容的知识产权的基础上,该等衍生产品的相关知识产权归种草短剧</u></em></strong><strong><em><u>及其关联公司或种草短剧</u></em></strong><strong><em><u>所授权许可的第三方所有。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>您确认并同意授权种草短剧</u></em></strong><strong><em><u>及其关联公司以自己的名义或委托专业第三方针对有关您上传、提交、存储或发布的内容(含衍生作品)的侵权行为进行独立自主的维权并获得全部赔偿。维权形式包括但不限于:监测侵权行为、发送维权函、提起诉讼或仲裁、调解、和解等。种草短剧</u></em></strong><strong><em><u>及其关联公司有权对维权事宜做出独立决策并予以实施。</u></em></strong></p>
|
||||||
|
<p><strong>8</strong><strong>、 </strong><strong>用户的违约及处理</strong></p>
|
||||||
|
<p>8.1 发生如下情形之一的,视为您违约:</p>
|
||||||
|
<p>(1)使用种草短剧平台服务时违反有关法律法规规定的;</p>
|
||||||
|
<p>(2)违反本协议或本协议补充协议(若有)约定的的内容。</p>
|
||||||
|
<p>您理解并同意,种草短剧可在种草短剧平台规则中约定违约认定的程序和标准。</p>
|
||||||
|
<p><strong><em><u>8.2 </u></em></strong><strong><em><u>违约处理措施</u></em></strong></p>
|
||||||
|
<p><strong><em><u>信息处理:您在种草短剧</u></em></strong><strong><em><u>平台上的任何行为构成违约的,种草短剧</u></em></strong><strong><em><u>可立即对相应信息进行删除、屏蔽处理,并通过合适的形式通知您。若删除操作必须由您本人操作完成,则您应在接到平台通知后立即删除相应信息。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>行为限制:您在种草短剧</u></em></strong><strong><em><u>平台上实施的行为,或虽未在种草短剧</u></em></strong><strong><em><u>平台上实施但对种草短剧</u></em></strong><strong><em><u>平台及其用户产生影响的行为构成违约的,种草短剧</u></em></strong><strong><em><u>有权做出独立判断并采取暂停提供部分或全部服务、冻结账户内余额、查封或注销账户、终止提供服务等措施,且无需因此对您进行任何赔偿或补偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>8.3 </u></em></strong><strong><em><u>赔偿责任</u></em></strong></p>
|
||||||
|
<p><strong><em><u>如您的行为使种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司遭受损失(包括自身的直接经济损失、商誉损失及对外支付的赔偿金、和解款、律师费、诉讼费等间接经济损失),您应赔偿种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司的上述全部损失。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>如您的行为使种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司遭受第三人主张权利,种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司可在对第三人承担金钱给付等义务后就全部损失向您追偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>如因您的行为使得第三人遭受损失或您怠于履行调处决定,种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司出于社会公共利益保护或消费者权益保护目的,可先行代您支付上述款项,您应当返还该部分费用并赔偿因此造成种草短剧</u></em></strong><strong><em><u>的全部损失。种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或关联公司也可直接抵减您在种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司其它协议项下的权益,并可继续追偿。</u></em></strong></p>
|
||||||
|
<p><strong>9</strong><strong>、 </strong><strong>通知</strong></p>
|
||||||
|
<p>9.1 有效联系方式</p>
|
||||||
|
<p>您理解并同意,种草短剧可以通过电子邮件、站内信息、手机短信、网站公告或其他方式向您发送活动信息、推广信息等各类信息。<strong><u>对于联系方式发生变更的,您有义务及时更新有关信息,并保持可被联系的状态。</u></strong><strong><u> </u></strong></p>
|
||||||
|
<p>9.2 通知的送达</p>
|
||||||
|
<p>种草短剧通过上述联系方式向您发出通知,其中以电子的方式发出的书面通知,包括但不限于在种草短剧平台显著位置刊登电子信息,向您提供的联系电话发送手机短信,向您提供的电子邮件地址发送电子邮件,向您的账户发送系统消息或站内信信息,在发送成功或刊登完成后即视为送达;以纸质载体发出的书面通知,按照提供联系地址交邮后的第五个自然日即视为送达。</p>
|
||||||
|
<p>上述送达方式同样可适用于相关仲裁或司法程序(含起诉、审理、执行等各阶段)。您应当保证所提供的联系方式是准确、有效的,并进行实时更新。如果因提供的联系方式不确切,或不及时告知变更后的联系方式,或其他不可归责于种草短剧的原因,使相关通知、文件、法律文书无法送达或未及时送达,由您自行承担由此可能产生的法律后果。</p>
|
||||||
|
<p><strong>10</strong><strong>、 </strong><strong>协议的终止</strong></p>
|
||||||
|
<p>10.1 终止的情形</p>
|
||||||
|
<p>用户发起的终止:您有权通过以下任一方式终止本协议:</p>
|
||||||
|
<p>(一)变更事项生效前您停止使用种草短剧服务并持续不再使用的;</p>
|
||||||
|
<p>(二)您明示不愿继续使用种草短剧服务,且符合种草短剧平台终止条件的。</p>
|
||||||
|
<p>种草短剧发起的终止:出现以下情况时,种草短剧可以本协议第9条的所列的方式通知您终止本协议:</p>
|
||||||
|
<p>(1)您违反本协议约定,种草短剧依据违约条款终止本协议的;</p>
|
||||||
|
<p>(2)您存在盗用他人账户、发布违禁信息、骗取他人财物、扰乱市场秩序、采取不正当手段谋利、侵犯他人合法权益等行为,种草短剧依据种草短剧平台规则对您的账户予以查封的;</p>
|
||||||
|
<p>(3)除上述情形外,因您多次违反种草短剧平台规则相关规定且情节严重,种草短剧依据种草短剧平台规则对您的账户予以查封的;</p>
|
||||||
|
<p>(4)种草短剧平台根据自身商业安排经过合理的提前通知终止全部种草短剧平台服务的;</p>
|
||||||
|
<p>(5)其它应当终止服务的情况。</p>
|
||||||
|
<p><strong>10.2 </strong><strong>协议终止后的处理</strong></p>
|
||||||
|
<p><strong>10.2.1 </strong><strong>服务终止:本协议终止后,种草短剧</strong><strong>平台将无法继续向您提供任何服务或履行任何其他义务,包括但不限于为您保留或向您披露其原种草短剧</strong><strong>账户中的任何信息,向您或第三方转发任何未曾阅读或发送过的信息等。 </strong></p>
|
||||||
|
<p><strong>10.2.2 </strong><strong>本协议终止后,种草短剧</strong><strong>仍享有下列权利:</strong></p>
|
||||||
|
<p><strong>(一)根据本协议及种草短剧</strong><strong>平台《隐私权政策》的相关约定,继续保存您留存于种草短剧</strong><strong>平台的各类信息;</strong></p>
|
||||||
|
<p><strong>(二)对于您过往的违约行为,种草短剧</strong><strong>仍可依据本协议向您追究违约责任。</strong></p>
|
||||||
|
<p>11、其他</p>
|
||||||
|
<p>11.1本协议之成立、生效、履行、解释及争议、纠纷解决,适用中华人民共和国大陆地区法律(不包括冲突法)。您同意因本协议引起的或与本协议有关的任何争议或纠纷在无法协商一致时,可向<strong><em><u>浙江省杭州市余杭区人民法院</u></em></strong>起诉,通过诉讼方式解决。</p>
|
||||||
|
<p>11.2本协议之任何部分与相关法律法规相抵触,则该部分条款应按法律法规规定重新解释。本协议部分条款之无效或重新解释不影响其它条款之法律效力。</p>
|
||||||
|
<p>11.3本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议条款解释的依据。</p>
|
||||||
|
<p>11.4本协议条款无论因何种原因部分无效或不可执行,其余条款仍有效,对双方具有约束力。</p></div></div>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
padding: 20upx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="2">
|
||||||
|
<view class="p-20">
|
||||||
|
<view class="wage p-30 flex flex-col">
|
||||||
|
<view class="wage-tip">总收益(元)</view>
|
||||||
|
<view class="money">{{(topData.totalMoney / 100).toFixed(2)}}</view>
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<view class="flex justify-between" style="padding: 10upx 0;">
|
||||||
|
<view><text class="wage-tip">今日预估</text><text class="nums">{{(topData.todayEstimate/100).toFixed(2)}}</text></view>
|
||||||
|
<view><text class="wage-tip">七日预估</text><text class="nums">{{(topData.sevenDaysEstimate/100).toFixed(2)}}</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="flex justify-between" style="padding: 10upx 0;">
|
||||||
|
<view><text class="wage-tip">昨日预估</text><text class="nums">{{(topData.yesterdayEstimate/100).toFixed(2)}}</text></view>
|
||||||
|
<view><text class="wage-tip">本月预估</text><text class="nums">{{(topData.thisMonthEstimate/100).toFixed(2)}}</text></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="short-play p-20">
|
||||||
|
<view class="flex flex-row justify-between items-center">
|
||||||
|
<view>
|
||||||
|
<text class="title">短剧数据</text>
|
||||||
|
<text class="date">2024-01-01</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-row justify-center items-center" @click="navigateTo('/pages/data/shortPlay/shortPlay')">
|
||||||
|
<text>更多</text>
|
||||||
|
<u-icon name="arrow-right"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-row">
|
||||||
|
<view class="flex-1">
|
||||||
|
<view class="p2">预估收益</view>
|
||||||
|
<view class="m2">0.00</view>
|
||||||
|
<view class="flex flex-row justify-between extra">
|
||||||
|
<text>退款金额</text>
|
||||||
|
<text>0.00</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1" style="margin-left: 20upx;">
|
||||||
|
<view class="p2">充值金额</view>
|
||||||
|
<view class="m2">0.00</view>
|
||||||
|
<view class="flex flex-row justify-between extra">
|
||||||
|
<text>广告收益</text>
|
||||||
|
<text>0.00</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<u-modal :show="showMini" title="长按二维码识别关注公众号" :closeOnClickOverlay="true" :showCancelButton="true"
|
||||||
|
cancelText="关闭" cancelColor="#007aff" :showConfirmButton="false" @close="showMini = false"
|
||||||
|
@cancel="showMini = false">
|
||||||
|
<view>
|
||||||
|
<view class="flex flex-col justify-center items-center" style="width: 100%;">
|
||||||
|
<image style="width: 300upx;height: 300upx;"
|
||||||
|
src="https://ly.imgother.hlh2021.com/1680836523536_小刘客服微信.jpg" mode="aspectFit"></image>
|
||||||
|
<view class="p-20">
|
||||||
|
<view style="color: red;font-size: 28upx;">关注后可以接受平台信息</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-modal>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
import {
|
||||||
|
record
|
||||||
|
} from '@/api/index.js'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CTabbar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showMini: false,
|
||||||
|
topData: {
|
||||||
|
sevenDaysEstimate: 0,
|
||||||
|
thisMonthEstimate: 0,
|
||||||
|
todayEstimate: 0,
|
||||||
|
totalMoney: 0,
|
||||||
|
yesterdayEstimate: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getData()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.getData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getData() {
|
||||||
|
const res = await record.statistics({})
|
||||||
|
this.topData = res.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wage {
|
||||||
|
background-color: $uni-theme;
|
||||||
|
border-radius: 20upx;
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
.wage-tip {
|
||||||
|
color: #84b6f9;
|
||||||
|
}
|
||||||
|
.money {
|
||||||
|
color: #f4f8ff;
|
||||||
|
font-size: 50upx;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-top: 15upx;
|
||||||
|
padding-bottom: 30upx;
|
||||||
|
}
|
||||||
|
.nums {
|
||||||
|
color: #f4f8ff;
|
||||||
|
margin-left: 15upx;
|
||||||
|
}
|
||||||
|
.short-play {
|
||||||
|
margin-top: 30upx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
color: #a0a0a0;
|
||||||
|
.title {
|
||||||
|
font-size: 40upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #303030;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
font-size: 28upx;
|
||||||
|
margin-left: 20upx;
|
||||||
|
}
|
||||||
|
.p2 {
|
||||||
|
font-size: 25upx;
|
||||||
|
padding-top: 20upx;
|
||||||
|
padding-bottom: 10upx;
|
||||||
|
}
|
||||||
|
.m2 {
|
||||||
|
font-size: 45upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
padding-bottom: 20upx;
|
||||||
|
}
|
||||||
|
.extra {
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
border-radius: 10upx;
|
||||||
|
padding: 10upx;
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,403 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20 container">
|
||||||
|
<view class="search-block flex flex-row items-center justify-between">
|
||||||
|
<u-tabs :list="tabs" lineWidth="30" lineColor="#007aff" :activeStyle="{
|
||||||
|
color: '#303133',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
transform: 'scale(1.05)'
|
||||||
|
}" :inactiveStyle="{
|
||||||
|
color: '#606266',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
}" itemStyle="padding-left: 8px; padding-right: 8px; height: 34px;" @change="changePlatformTab">
|
||||||
|
</u-tabs>
|
||||||
|
<view>
|
||||||
|
<sl-filter :ref="'slFilter'" :topFixed="false" :isTransNav="true" :navHeight="0" :color="titleColor"
|
||||||
|
:themeColor="themeColor" :tabHeight="30" :menuList="menuList" @result="result"></sl-filter>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="tags flex flex-row">
|
||||||
|
<view :class="['tag', tagCurrent === index && 'active' ]" v-for="(item, index) in tagList" :key="item.value"
|
||||||
|
@click="changeTab(index)">{{item.name}}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="amount flex flex-col">
|
||||||
|
<view class="flex flex-row">
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="t1">预估收益</text>
|
||||||
|
<text class="m1">¥ {{(topStatics.estimateEarnings/100).toFixed(2)}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="t1">充值金额</text>
|
||||||
|
<text class="m1">¥ {{(topStatics.rechargeMoney/100).toFixed(2)}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="t1">退款金额</text>
|
||||||
|
<text class="m1">¥ {{(topStatics.refundMoney/100).toFixed(2)}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="flex flex-row" style="margin-top: 20upx;">
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="t1">预估收益</text>
|
||||||
|
<text class="m1">¥ 0.00</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="t1">点击人数</text>
|
||||||
|
<text class="m1">0</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="t1">点击次数</text>
|
||||||
|
<text class="m1">0</text>
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="income p-d-20">
|
||||||
|
<view>收益明细</view>
|
||||||
|
<view class="flex flex-row">
|
||||||
|
<view :class="['type-tag', earningsType === 1 && 'active']" @click="changeEarnType(1)">充值收益</view>
|
||||||
|
<view :class="['type-tag', earningsType === 2 && 'active']" @click="changeEarnType(2)">广告收益</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="p-d-20">
|
||||||
|
<view class="information p-20 flex flex-row">
|
||||||
|
<image class="img" src="" mode="widthFix"></image>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<view class="flex flex-row justify-between items-center">
|
||||||
|
<view><text>章章剧场</text></view>
|
||||||
|
<text class="red">即将到账</text>
|
||||||
|
</view>
|
||||||
|
<view class="title ellipsis">老公的金丝雀怀孕后老</view>
|
||||||
|
<text>付款时间:20223-23-02 00:00:00</text>
|
||||||
|
<view class="wage1 flex flex-row justify-between">
|
||||||
|
<text>付款金额:200</text>
|
||||||
|
<text>预计收入:16.8</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="information p-20 flex flex-row">
|
||||||
|
<image class="img" src="" mode="widthFix"></image>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<view class="flex flex-row justify-between items-center">
|
||||||
|
<view><text>章章剧场</text></view>
|
||||||
|
<text class="red">即将到账</text>
|
||||||
|
</view>
|
||||||
|
<view class="title ellipsis">老公的金丝雀怀孕后老</view>
|
||||||
|
<text>付款时间:20223-23-02 00:00:00</text>
|
||||||
|
<view class="wage1 flex flex-row justify-between">
|
||||||
|
<text>付款金额:200</text>
|
||||||
|
<text>预计收入:16.8</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="information p-20 flex flex-row">
|
||||||
|
<image class="img" src="" mode="widthFix"></image>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<view class="flex flex-row justify-between items-center">
|
||||||
|
<view><text>章章剧场</text></view>
|
||||||
|
<text class="red">即将到账</text>
|
||||||
|
</view>
|
||||||
|
<view class="title ellipsis">老公的金丝雀怀孕后老</view>
|
||||||
|
<text>付款时间:20223-23-02 00:00:00</text>
|
||||||
|
<view class="wage1 flex flex-row justify-between">
|
||||||
|
<text>付款金额:200</text>
|
||||||
|
<text>预计收入:16.8</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
record,
|
||||||
|
getTypeList
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
currentDate
|
||||||
|
} from '@/utils/common.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
themeColor: '#007aff',
|
||||||
|
titleColor: '#666666',
|
||||||
|
tabs: [{
|
||||||
|
name: '全部'
|
||||||
|
}, {
|
||||||
|
name: '抖音'
|
||||||
|
}, {
|
||||||
|
name: '快手'
|
||||||
|
}, {
|
||||||
|
name: '视频号'
|
||||||
|
}],
|
||||||
|
menuList: [{
|
||||||
|
'title': '全部剧场',
|
||||||
|
'isMutiple': false,
|
||||||
|
'key': 'playSource',
|
||||||
|
'defaultSelectedIndex': 0,
|
||||||
|
'detailList': []
|
||||||
|
|
||||||
|
}],
|
||||||
|
tagList: [{
|
||||||
|
name: '今天',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '昨天',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '7天',
|
||||||
|
value: 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '15天',
|
||||||
|
value: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '本月',
|
||||||
|
value: 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '上月',
|
||||||
|
value: 60
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tagCurrent: 0,
|
||||||
|
filter: {
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
sourcePlatform: '',
|
||||||
|
playletItemId: ''
|
||||||
|
},
|
||||||
|
topStatics: {
|
||||||
|
estimateEarnings: 0,
|
||||||
|
rechargeMoney: 0,
|
||||||
|
refundMoney: 0
|
||||||
|
},
|
||||||
|
earningsType: 1,
|
||||||
|
list: [],
|
||||||
|
height: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 在页面中使用 , this是当前页面中的this, arr 是包含dom类名的数组
|
||||||
|
async onReady() {
|
||||||
|
// 顶部搜索栏 和 轮播图 的类名
|
||||||
|
let arr = ['.search-block','.tags', '.amount', '.income']
|
||||||
|
this.height = await this.getScrollViewHeight(this, arr)
|
||||||
|
this.getList(1)
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.filter.startTime = currentDate() + ' 00:00:00'
|
||||||
|
this.filter.endTime = currentDate() + ' 00:00:00'
|
||||||
|
this.getPlayType()
|
||||||
|
this.getTopStatics()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getSystemInfo(key) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
uni.getSystemInfo({
|
||||||
|
success(res) {
|
||||||
|
key ? resolve(res[key]) : resolve(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getDomHeight(_this, selector) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
const query = uni.createSelectorQuery().in(_this);
|
||||||
|
query.select(selector).boundingClientRect(data => {
|
||||||
|
resolve(data.height)
|
||||||
|
}).exec();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async getScrollViewHeight(_this, arr) {
|
||||||
|
let height = 0
|
||||||
|
let windowHeight = await this.getSystemInfo('windowHeight')
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
let h = await this.getDomHeight(_this, arr[i])
|
||||||
|
height += h
|
||||||
|
}
|
||||||
|
return windowHeight - height
|
||||||
|
},
|
||||||
|
async getPlayType() {
|
||||||
|
const res = await getTypeList({})
|
||||||
|
const getData = res.data.map(i => {
|
||||||
|
return {
|
||||||
|
title: i.name,
|
||||||
|
value: i.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.menuList[0].detailList = [{
|
||||||
|
'title': '全部剧场',
|
||||||
|
'value': ''
|
||||||
|
},
|
||||||
|
...getData
|
||||||
|
]
|
||||||
|
},
|
||||||
|
async getTopStatics() {
|
||||||
|
const res = await record.statisticsTimeType(this.filter)
|
||||||
|
if (!res.success) return
|
||||||
|
this.topStatics.estimateEarnings = res.data.estimateEarnings
|
||||||
|
this.topStatics.rechargeMoney = res.data.rechargeMoney
|
||||||
|
this.topStatics.refundMoney = res.data.refundMoney
|
||||||
|
},
|
||||||
|
result(val) {
|
||||||
|
this.filter.playletItemId = val.playSource
|
||||||
|
this.getTopStatics()
|
||||||
|
},
|
||||||
|
changePlatformTab(e) {
|
||||||
|
this.filter.sourcePlatform = e.index ? e.index : ''
|
||||||
|
this.getTopStatics()
|
||||||
|
},
|
||||||
|
changeTab(index) {
|
||||||
|
if (this.tagCurrent === index) return;
|
||||||
|
this.tagCurrent = index
|
||||||
|
const range = this.tagList[this.tagCurrent].value
|
||||||
|
this.filter.startTime = currentDate() + ' 00:00:00'
|
||||||
|
this.filter.endTime = currentDate(false, -range) + ' 00:00:00'
|
||||||
|
this.getTopStatics()
|
||||||
|
},
|
||||||
|
changeEarnType(index) {
|
||||||
|
if(this.earningsType === index) return
|
||||||
|
this.earningsType = index;
|
||||||
|
this.search()
|
||||||
|
},
|
||||||
|
search(){
|
||||||
|
this.list = [];
|
||||||
|
this.mescroll.resetUpScroll();
|
||||||
|
},
|
||||||
|
async getList(pageNum) {
|
||||||
|
const res = await record.getRecordList(pageNum, 10, {
|
||||||
|
...this.filter,
|
||||||
|
earningsType: this.earningsType
|
||||||
|
})
|
||||||
|
if(res.success) {
|
||||||
|
this.mescroll.endBySize(res.data.list.length, parseInt(res.data.total));
|
||||||
|
if (pageNum == 1) this.list = []; //如果是第一页需手动制空列表
|
||||||
|
this.list = this.list.concat(res.data.list);
|
||||||
|
} else {
|
||||||
|
this.mescroll.endErr();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upCallback(page) {
|
||||||
|
this.getList(page.num)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
background: linear-gradient(to bottom, #c6d9f7, #f0f5fc, #ffffff);
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
padding: 20upx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
width: 93.33upx;
|
||||||
|
border-radius: 10upx;
|
||||||
|
padding: 10upx 0;
|
||||||
|
color: #3a5184;
|
||||||
|
background-color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 30upx;
|
||||||
|
margin-right: 30upx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #2a6cc4;
|
||||||
|
background-color: #d5e5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount {
|
||||||
|
border-radius: 20upx;
|
||||||
|
padding: 50upx 0;
|
||||||
|
margin-top: 20upx;
|
||||||
|
background: linear-gradient(to right, #5a7cfe, #055de9);
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t1 {
|
||||||
|
font-size: 24upx;
|
||||||
|
color: #8eadfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m1 {
|
||||||
|
font-size: 30upx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-top: 10upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-tag {
|
||||||
|
padding: 10upx 20upx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
font-size: 25upx;
|
||||||
|
margin-right: 10upx;
|
||||||
|
border-radius: 10upx;
|
||||||
|
margin-top: 20upx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $uni-theme;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.information {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
margin-bottom: 20upx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 150upx;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 10upx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
padding-left: 20upx;
|
||||||
|
width: 500upx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
color: #323333;
|
||||||
|
font-size: 30upx;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 10upx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red {
|
||||||
|
color: $u-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 25upx;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wage1 {
|
||||||
|
padding-top: 10upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wage1 text {
|
||||||
|
color: $u-main-color;
|
||||||
|
font-size: 27upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="img-a">
|
||||||
|
<image src="../../static/head.png" mode="aspectFill"></image>
|
||||||
|
<view class="t-b">
|
||||||
|
您好,
|
||||||
|
<br />
|
||||||
|
欢迎使用 种草短剧
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="login-view" style="">
|
||||||
|
<view class="t-login">
|
||||||
|
<form class="cl">
|
||||||
|
<button @tap="login()">微信登录/注册</button>
|
||||||
|
<view class="reg" @tap="navigateTo('/pages/login/login')">账号密码登录</view>
|
||||||
|
</form>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
codeGetOpenID,
|
||||||
|
loginByOpenid
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import { mapMutations } from 'vuex'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onLoad() {},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['setToken', 'setUserInfo']),
|
||||||
|
//当前登录按钮操作
|
||||||
|
login() {
|
||||||
|
this.getOpenId()
|
||||||
|
},
|
||||||
|
async getOpenId() {
|
||||||
|
const code = await this.authLogin()
|
||||||
|
const res = await codeGetOpenID({code})
|
||||||
|
this.setToken(res.msg)
|
||||||
|
const res1 = await loginByOpenid({openid: res.msg})
|
||||||
|
this.setUserInfo(res1.data)
|
||||||
|
if(res1.data.phone && res1.data.password) {
|
||||||
|
uni.showToast({ title: '登录成功!', icon: 'success' });
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/home/mini/mini'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/register/register'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
authLogin() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.login({
|
||||||
|
provider: 'weixin',
|
||||||
|
success: (res) => {
|
||||||
|
console.log('code', res.code);
|
||||||
|
if (res.errMsg == 'login:ok') {
|
||||||
|
resolve(res.code)
|
||||||
|
} else {
|
||||||
|
reject('登录失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
page{
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.txt {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.img-a {
|
||||||
|
width: 100%;
|
||||||
|
height: 550rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.img-a image {
|
||||||
|
width: 100%;
|
||||||
|
height: 550rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reg {
|
||||||
|
font-size: 35rpx;
|
||||||
|
color: #fff;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
background: #f5f6fa;
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-view {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin-top: -120rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 40rpx 40rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login {
|
||||||
|
width: 85vw;
|
||||||
|
margin: 0 auto;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding-top: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login button {
|
||||||
|
font-size: 35rpx;
|
||||||
|
background: #2796f2;
|
||||||
|
color: #fff;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
}
|
||||||
|
.t-b {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 42rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 130rpx 0 0 70rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 70rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="0">
|
||||||
|
<view class="container">
|
||||||
|
<view>
|
||||||
|
<u-swiper :list="list3" indicator indicatorMode="line" circular></u-swiper>
|
||||||
|
</view>
|
||||||
|
<view class="p-d-20">
|
||||||
|
<u-notice-bar :text="notice" mode="link" bgColor="#fff" color="#323333" speed="100"
|
||||||
|
url="/pages/notice/notice"></u-notice-bar>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-row justify-between menu">
|
||||||
|
<image class="big-img" src="../../../static/home/group.png" mode="widthFix"></image>
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<image class="small-img" src="../../../static/home/play.png" mode="aspectFit"></image>
|
||||||
|
<image class="small-img" src="../../../static/home/wechat.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view style="padding: 10upx 0;">
|
||||||
|
<image style="width: 100%;" src="../../../static/home/program.png" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CTabbar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
notice: '【抖音短剧分发】麻雀短剧结算提前了同学们; 新年开工啦!; 【抖音短剧分发】2024年春节放假通知; 快手短剧通知; 年会; ',
|
||||||
|
list3: [
|
||||||
|
'https://cdn.uviewui.com/uview/swiper/swiper3.png',
|
||||||
|
'https://cdn.uviewui.com/uview/swiper/swiper2.png',
|
||||||
|
'https://cdn.uviewui.com/uview/swiper/swiper1.png',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
background: #f7f8fa;
|
||||||
|
padding: 30upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
height: 310upx;
|
||||||
|
|
||||||
|
>view {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-img {
|
||||||
|
width: 46vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-img {
|
||||||
|
width: 46vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-30">
|
||||||
|
<view style="padding: 10upx 0;position: relative;" v-if="info" @click="videoFullScreenShow = true">
|
||||||
|
<image style="width: 100%;" :src="info.imgUrl" mode="widthFix"></image>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="bg-white p-20 rounded" v-if="info && info.detailContent">
|
||||||
|
<rich-text :nodes="info.detailContent"></rich-text>
|
||||||
|
</view>
|
||||||
|
<view class="bg-white bottom p-30">
|
||||||
|
<u-button shape="circle" type="primary">我要加入</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 全屏播放视频 -->
|
||||||
|
<video-full-screen v-model="videoFullScreenShow" :src="info.detailVideoUrl" @exit="exit()">
|
||||||
|
</video-full-screen>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import videoFullScreen from '@/components/video-full-screen/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
components: {
|
||||||
|
videoFullScreen
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
info: null,
|
||||||
|
videoFullScreenShow: false, // 是否全屏显示视频
|
||||||
|
videoplayObj: {}, //video对象
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(option) {
|
||||||
|
this.info = JSON.parse(option.item)
|
||||||
|
this.info.detailContent = this.escape2Html(uni.getStorageSync('detailContent'))
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: this.info.name
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.videoplayObj = wx.createVideoContext('myVideo')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
exit() {
|
||||||
|
this.videoFullScreenShow = false;
|
||||||
|
this.videoplayObj.pause()
|
||||||
|
},
|
||||||
|
|
||||||
|
escape2Html(str) {
|
||||||
|
var arrEntities = {
|
||||||
|
'lt': '<',
|
||||||
|
'gt': '>',
|
||||||
|
'nbsp': ' ',
|
||||||
|
'amp': '&',
|
||||||
|
'quot': '"'
|
||||||
|
};
|
||||||
|
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function(all, t) {
|
||||||
|
return arrEntities[t];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.bottom {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="0">
|
||||||
|
<view class="container">
|
||||||
|
<view>
|
||||||
|
<u-swiper :list="list3" indicator indicatorMode="line" circular @click="clickSwiper"></u-swiper>
|
||||||
|
</view>
|
||||||
|
<view class="operations flex flex-row">
|
||||||
|
<view class="item b1">
|
||||||
|
<text class="t1">邀请好友</text>
|
||||||
|
<text class="t2">赚高额提成</text>
|
||||||
|
</view>
|
||||||
|
<view class="item b2">
|
||||||
|
<text class="t1">App下载</text>
|
||||||
|
<text class="t2">点击去下载</text>
|
||||||
|
</view>
|
||||||
|
<view class="item b3" @click="show = true">
|
||||||
|
<text class="t1">客服微信</text>
|
||||||
|
<text class="t2">疑问解答</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="p-d-20">
|
||||||
|
<u-notice-bar :text="notice" mode="link" bgColor="#fff" color="#323333" speed="80"
|
||||||
|
url="/pages/notice/notice"></u-notice-bar>
|
||||||
|
</view>
|
||||||
|
<view style="padding: 10upx 0;">
|
||||||
|
<image style="width: 100%;" src="../../../static/home/app.png" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view style="padding: 10upx 0;">
|
||||||
|
<image style="width: 100%;" src="../../../static/home/feedback.png" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="title">变现项目</view>
|
||||||
|
<view style="padding: 10upx 0;">
|
||||||
|
<image style="width: 100%;margin-bottom: 20upx;" v-for="item in project" :key="item.id" :src="item.imgUrl" @click="goDetail(item)" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<c-loading v-if="loading"><u-loading-icon mode="circle"></u-loading-icon></c-loading>
|
||||||
|
|
||||||
|
<service-modal :show="show" @close="show = false"></service-modal>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
import CLoading from '@/components/gLoading.vue'
|
||||||
|
import serviceModal from '@/components/modal/serviceModal.vue'
|
||||||
|
import {
|
||||||
|
getBannerList,
|
||||||
|
getProjectList,
|
||||||
|
getMessageList
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CTabbar,
|
||||||
|
CLoading,
|
||||||
|
serviceModal
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo', 'token'])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
notice: '',
|
||||||
|
list3: [],
|
||||||
|
project: [],
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
uni.hideTabBar()
|
||||||
|
this.getContent()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getUserInfo']),
|
||||||
|
async getContent() {
|
||||||
|
const res = await getBannerList({})
|
||||||
|
this.list3 = res.data
|
||||||
|
const res1 = await getProjectList({})
|
||||||
|
this.project = res1.data
|
||||||
|
const res2 = await getMessageList({type: '02'})
|
||||||
|
const strArr = res2.data.map(item => {
|
||||||
|
return item.title
|
||||||
|
})
|
||||||
|
this.notice = strArr.join(';')
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
goDetail(item) {
|
||||||
|
uni.setStorageSync('detailContent',item.detailContent)
|
||||||
|
const newItem = {...item, detailContent: ''}
|
||||||
|
this.navigateTo(`/pages/home/mini/info/info?item=${JSON.stringify(newItem)}`)
|
||||||
|
},
|
||||||
|
clickSwiper(index) {
|
||||||
|
this.navigateTo(`/pages/home/mini/viewImg/viewImg?url=${this.list3[index].detailUrl}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
background: #f7f8fa;
|
||||||
|
padding: 30upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operations {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 10upx;
|
||||||
|
padding: 20upx;
|
||||||
|
margin-top: 20upx;
|
||||||
|
|
||||||
|
.b1 {
|
||||||
|
background-color: #fffaf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.b2 {
|
||||||
|
background-color: #f5f8ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.b3 {
|
||||||
|
background-color: #f3fafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
padding: 15upx 20upx;
|
||||||
|
margin: 0 10upx;
|
||||||
|
border-radius: 10upx;
|
||||||
|
|
||||||
|
.t1 {
|
||||||
|
font-size: 30upx;
|
||||||
|
color: #44413b;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t2 {
|
||||||
|
font-size: 24upx;
|
||||||
|
color: #bbc3c3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding: 20upx 0;
|
||||||
|
font-size: 35upx;
|
||||||
|
color: #44413b;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<image :src="src" mode="widthFix" style="width: 100%;"></image>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
src: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(option) {
|
||||||
|
this.src = option.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
|
||||||
|
<view class="intro">本项目已包含uni ui组件,无需import和注册,可直接使用。在代码区键入字母u,即可通过代码助手列出所有可用组件。光标置于组件名称处按F1,即可查看组件文档。</view>
|
||||||
|
<text class="intro">详见:</text>
|
||||||
|
<uni-link :href="href" :text="href"></uni-link>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
href: 'https://uniapp.dcloud.io/component/README?id=uniui'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="img-a">
|
||||||
|
<image src="../../../static/head.png" mode="aspectFill"></image>
|
||||||
|
<view class="t-b">
|
||||||
|
您好,
|
||||||
|
<br />
|
||||||
|
欢迎使用 种草短剧
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="login-view" style="">
|
||||||
|
<view class="p-30">
|
||||||
|
<u--form :model="form" :rules="rules" ref="uForm">
|
||||||
|
<u-form-item prop="phone">
|
||||||
|
<u-input v-model="form.phone" :readonly="initHasPhone" placeholder="请输入手机号" clearable />
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item prop="code" borderBottom>
|
||||||
|
<u-input v-model="form.code" placeholder="请填写验证码" clearable>
|
||||||
|
<template slot="suffix">
|
||||||
|
<u-code ref="uCode" @change="codeChange" seconds="60" @start="disabled1 = true"
|
||||||
|
@end="disabled1 = false"></u-code>
|
||||||
|
<u-button @tap="getCode" :text="tips" type="primary" size="mini"
|
||||||
|
:disabled="disabled1"></u-button>
|
||||||
|
</template>
|
||||||
|
</u-input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item prop="password">
|
||||||
|
<u-input v-model="form.password" password type="password" clearable placeholder="请输入密码" />
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item prop="rePassword">
|
||||||
|
<u-input v-model="form.rePassword" password type="password" clearable placeholder="请再次输入密码" />
|
||||||
|
</u-form-item>
|
||||||
|
</u--form>
|
||||||
|
</view>
|
||||||
|
<view class="t-login">
|
||||||
|
<form class="cl">
|
||||||
|
<button @tap="submit()">保存</button>
|
||||||
|
<view class="reg" @tap="navigateBack()" v-if="!initHasPhone">返回登录</view>
|
||||||
|
</form>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
updateUserById,
|
||||||
|
sendSmsCode,
|
||||||
|
updatePasswordByCode
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
disabled1: false,
|
||||||
|
tips: '',
|
||||||
|
initHasPhone: false,
|
||||||
|
form: {
|
||||||
|
phone: '',
|
||||||
|
code: '',
|
||||||
|
password: '',
|
||||||
|
rePassword: ''
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// 字段名称
|
||||||
|
phone: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入手机号',
|
||||||
|
trigger: ['change', 'blur'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 自定义验证函数,见上说明
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
// uni.$u.test.mobile()就是返回true或者false的
|
||||||
|
return uni.$u.test.mobile(value);
|
||||||
|
},
|
||||||
|
message: '手机号码不正确',
|
||||||
|
trigger: ['change', 'blur'],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
code: {
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
len: 6,
|
||||||
|
message: '请填写6位验证码',
|
||||||
|
trigger: ['blur']
|
||||||
|
},
|
||||||
|
password: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入密码',
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}],
|
||||||
|
rePassword: [{
|
||||||
|
required: true,
|
||||||
|
message: '请再次输入密码',
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(option) {
|
||||||
|
if(option.phone) {
|
||||||
|
this.initHasPhone = true
|
||||||
|
this.form.phone = option.phone
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
//如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则。
|
||||||
|
this.$refs.uForm.setRules(this.rules)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit() {
|
||||||
|
this.$refs.uForm.validate().then(async res => {
|
||||||
|
if (this.form.password !== this.form.rePassword) {
|
||||||
|
return uni.$u.toast('两次密码不一致,请重新输入')
|
||||||
|
}
|
||||||
|
const res1 = await updatePasswordByCode(this.form)
|
||||||
|
if (!res1.success) return
|
||||||
|
uni.showToast({
|
||||||
|
title: '操作成功,即将返回上一页',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
success() {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(errors => {
|
||||||
|
// uni.$u.toast('校验失败')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
codeChange(text) {
|
||||||
|
this.tips = text;
|
||||||
|
},
|
||||||
|
async getCode() {
|
||||||
|
if (this.$refs.uCode.canGetCode) {
|
||||||
|
if (!/^[1][3,4,5,7,8,9][0-9]{9}$/.test(this.form.phone)) {
|
||||||
|
uni.$u.toast('请输入正确手机号')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await sendSmsCode({phone: this.form.phone})
|
||||||
|
if(!res.success) return
|
||||||
|
// 这里此提示会被this.start()方法中的提示覆盖
|
||||||
|
uni.$u.toast('验证码已发送');
|
||||||
|
// 通知验证码组件内部开始倒计时
|
||||||
|
this.$refs.uCode.start();
|
||||||
|
} else {
|
||||||
|
console.info('倒计时结束后再发送');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-a {
|
||||||
|
width: 100%;
|
||||||
|
height: 550rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-a image {
|
||||||
|
width: 100%;
|
||||||
|
height: 550rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reg {
|
||||||
|
font-size: 35rpx;
|
||||||
|
color: #fff;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
background: #f5f6fa;
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-view {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin-top: -120rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 40rpx 40rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login {
|
||||||
|
width: 85vw;
|
||||||
|
margin: 0 auto;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login button {
|
||||||
|
font-size: 35rpx;
|
||||||
|
background: #2796f2;
|
||||||
|
color: #fff;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-b {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 42rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 130rpx 0 0 70rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 70rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="img-a">
|
||||||
|
<image src="../../static/head.png" mode="aspectFill"></image>
|
||||||
|
<view class="t-b">
|
||||||
|
您好,
|
||||||
|
<br />
|
||||||
|
欢迎使用 种草短剧
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="login-view" style="">
|
||||||
|
<view class="t-login">
|
||||||
|
<form class="cl">
|
||||||
|
<view class="t-a">
|
||||||
|
<!-- <text class="txt">手机号</text> -->
|
||||||
|
<input type="number" name="phone" placeholder="请输入您的手机号" maxlength="11" v-model="phone" />
|
||||||
|
</view>
|
||||||
|
<view class="t-a">
|
||||||
|
<!-- <text class="txt">密码</text> -->
|
||||||
|
<input type="password" name="code" maxlength="18" placeholder="请输入您的密码" v-model="pwd" />
|
||||||
|
</view>
|
||||||
|
<view class="hint flex flex-row items-center">
|
||||||
|
<u-checkbox-group v-model="checked">
|
||||||
|
<u-checkbox shape="circle" size="30rpx"></u-checkbox>
|
||||||
|
</u-checkbox-group>
|
||||||
|
<view class="flex-1" @click="checked = ['']">
|
||||||
|
我已经阅读并同意 <text class="link" @click.stop="navigateTo(`/pages/agreement/user/user`)">《用户协议》</text>
|
||||||
|
和 <text class="link" @click.stop="navigateTo(`/pages/agreement/privacy/privacy`)">《隐私政策》</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<button @tap="login()">登 录</button>
|
||||||
|
<!-- <view class="reg" @tap="reg()">注 册</view> -->
|
||||||
|
</form>
|
||||||
|
<div class="texts">
|
||||||
|
<div>还没有账号?<span class="link-text" @click.stop="navigateTo(`/pages/register/register`)">立即注册</span></div>
|
||||||
|
<div @click.stop="navigateTo(`/pages/login/forgetPwd/forgetPwd`)">忘记密码?</div>
|
||||||
|
</div>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
loginByPassword
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import { mapMutations } from 'vuex'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
phone: '', //手机号码
|
||||||
|
pwd: '', //密码
|
||||||
|
checked: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onLoad() {},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['setUserInfo']),
|
||||||
|
//当前登录按钮操作
|
||||||
|
async login() {
|
||||||
|
if(!this.checked.length) return uni.$u.toast('请先阅读并同意用户隐私协议')
|
||||||
|
var that = this;
|
||||||
|
if (!that.phone) {
|
||||||
|
uni.$u.toast('请输入您的手机号')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!/^[1][3,4,5,7,8,9][0-9]{9}$/.test(that.phone)) {
|
||||||
|
uni.$u.toast('请输入正确手机号')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!that.pwd) {
|
||||||
|
uni.$u.toast('请输入您的密码')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await loginByPassword({
|
||||||
|
password: that.pwd,
|
||||||
|
phone: that.phone
|
||||||
|
})
|
||||||
|
if(!res.success) return
|
||||||
|
this.setUserInfo(res.data)
|
||||||
|
uni.showToast({
|
||||||
|
title: '登录成功!',
|
||||||
|
icon: 'none',
|
||||||
|
success() {
|
||||||
|
uni.reLaunch({
|
||||||
|
// #ifdef H5
|
||||||
|
url: '/pages/home/h5/h5',
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
url: '/pages/home/mini/mini'
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//注册按钮点击
|
||||||
|
reg() {
|
||||||
|
uni.navigateBack()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.txt {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-a {
|
||||||
|
width: 100%;
|
||||||
|
height: 550rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-a image {
|
||||||
|
width: 100%;
|
||||||
|
height: 550rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reg {
|
||||||
|
font-size: 35rpx;
|
||||||
|
color: #fff;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
background: #f5f6fa;
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-view {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin-top: -120rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 40rpx 40rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login {
|
||||||
|
width: 85vw;
|
||||||
|
margin: 0 auto;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding-top: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login button {
|
||||||
|
font-size: 35rpx;
|
||||||
|
background: #2796f2;
|
||||||
|
color: #fff;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login input {
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
border-bottom: 1px solid #e9e9e9;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-a {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-b {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 42rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 130rpx 0 0 70rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 70rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-c {
|
||||||
|
position: absolute;
|
||||||
|
right: 22rpx;
|
||||||
|
top: 22rpx;
|
||||||
|
background: $uni-theme;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
line-height: 50rpx;
|
||||||
|
padding: 0 25rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-d {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
margin: 80rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-e {
|
||||||
|
text-align: center;
|
||||||
|
width: 250rpx;
|
||||||
|
margin: 30rpx auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-g {
|
||||||
|
float: left;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-e image {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-f {
|
||||||
|
text-align: center;
|
||||||
|
margin: 60rpx 0 0 0;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .t-f text {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
color: #aaaaaa;
|
||||||
|
font-size: 27rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-login .uni-input-placeholder {
|
||||||
|
color: #aeaeae;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cl {
|
||||||
|
zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cl:after {
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
visibility: hidden;
|
||||||
|
height: 0;
|
||||||
|
content: '\20';
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
padding-bottom: 40upx;
|
||||||
|
font-size: 25rpx;
|
||||||
|
color: #909399;
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: $uni-theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.texts {
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
color: #999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-flow: row;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="bg-white box">
|
||||||
|
<view class="title">反馈类型</view>
|
||||||
|
<view>
|
||||||
|
<u-radio-group v-model="type" @change="changeType" :disabled="isUpdate" placement="row">
|
||||||
|
<u-radio label="功能建议" name="01"></u-radio>
|
||||||
|
<u-radio label="客服投诉" name="02"></u-radio>
|
||||||
|
<u-radio label="其他" name="03"></u-radio>
|
||||||
|
</u-radio-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="bg-white box">
|
||||||
|
<view class="title">问题和意见</view>
|
||||||
|
<view>
|
||||||
|
<u--textarea v-model="remark" :disabled="isUpdate" placeholder="请输入内容" count maxlength="200"></u--textarea>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="padding: 50rpx;" class="fixed-btn" v-if="!isUpdate">
|
||||||
|
<u-button shape="circle" type="primary" @click="submit()">提交</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
feedbackAdd
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
type: '01',
|
||||||
|
remark: '',
|
||||||
|
isUpdate: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(option) {
|
||||||
|
if (option.data) {
|
||||||
|
const jsonData = JSON.parse(option.data)
|
||||||
|
this.type = jsonData.type
|
||||||
|
this.remark = jsonData.content
|
||||||
|
this.isUpdate = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async submit() {
|
||||||
|
if (!this.remark) return uni.$u.toast('请输入问题和建议')
|
||||||
|
const res = await feedbackAdd({
|
||||||
|
userId: this.userInfo.id,
|
||||||
|
type: this.type,
|
||||||
|
content: this.remark
|
||||||
|
})
|
||||||
|
if (!res.success) return
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
success() {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.box {
|
||||||
|
border-radius: 20upx;
|
||||||
|
padding: 30upx;
|
||||||
|
margin-bottom: 20upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 30upx;
|
||||||
|
color: $u-info;
|
||||||
|
padding-bottom: 20upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .u-radio {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-btn {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-30">
|
||||||
|
<!-- <view class="c-menu">
|
||||||
|
<u-cell title="2024-01-01" isLink>
|
||||||
|
<template slot="value">
|
||||||
|
<text class="t-orange">待处理</text>
|
||||||
|
</template>
|
||||||
|
</u-cell>
|
||||||
|
<u-cell class="no-line" title="2024-01-01" isLink>
|
||||||
|
<template slot="value">
|
||||||
|
<text class="t-green">已处理</text>
|
||||||
|
</template>
|
||||||
|
</u-cell>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell :title="item.createTime" isLink v-for="item in list" :key="item.id" @click="goInfo(item)">
|
||||||
|
<!-- <template slot="value">
|
||||||
|
<text class="t-orange">待处理</text>
|
||||||
|
</template> -->
|
||||||
|
</u-cell>
|
||||||
|
</view>
|
||||||
|
</mescroll-body>
|
||||||
|
|
||||||
|
<view style="padding: 50rpx;" class="fixed-btn">
|
||||||
|
<u-button shape="circle" type="primary" @click="navigateTo('/pages/my/feedback/add/add')">新增意见反馈</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
feedbackList
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
mixins: [MescrollMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
if(this.mescroll) {
|
||||||
|
this.mescroll.resetUpScroll();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
goInfo(item) {
|
||||||
|
this.navigateTo('/pages/my/feedback/add/add?data='+JSON.stringify(item))
|
||||||
|
},
|
||||||
|
async getList(pageNum) {
|
||||||
|
const res = await feedbackList(pageNum, 20, {
|
||||||
|
userId: this.userInfo.id
|
||||||
|
})
|
||||||
|
if(res.success) {
|
||||||
|
this.mescroll.endBySize(res.data.list.length, parseInt(res.data.total));
|
||||||
|
if (pageNum == 1) this.list = []; //如果是第一页需手动制空列表
|
||||||
|
this.list = this.list.concat(res.data.list);
|
||||||
|
} else {
|
||||||
|
this.mescroll.endErr();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upCallback(page) {
|
||||||
|
this.getList(page.num)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.t-orange {
|
||||||
|
font-size: 28upx;
|
||||||
|
color: $u-warning-dark;
|
||||||
|
}
|
||||||
|
.t-green {
|
||||||
|
font-size: 28upx;
|
||||||
|
color: $u-success-dark;
|
||||||
|
}
|
||||||
|
.fixed-btn {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="2">
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="flex flex-row justify-center items-center" style="margin-bottom: 50upx;" @click="navigateTo('/pages/my/personal/personal')">
|
||||||
|
<view class="flex justify-center items-center">
|
||||||
|
<image class="avatar" src="../../../static/avatar.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1" style="padding-left: 20upx;">
|
||||||
|
<view class="name">{{userInfo.nickName}}</view>
|
||||||
|
<view class="c-666">{{userInfo.phone}}</view>
|
||||||
|
<view class="c-666">ID:{{userInfo.id}}</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-icon name="arrow-right"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell class="no-line" title="在线客服" :isLink="true" arrow-direction="right" @click="show = true"></u-cell>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell class="no-line" title="种草短剧小程序" :isLink="true" arrow-direction="right" @click="showMini = true"></u-cell>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell title="用户协议" :isLink="true" arrow-direction="right" url="/pages/agreement/user/user"></u-cell>
|
||||||
|
<u-cell title="隐私政策" class="no-line" :isLink="true" arrow-direction="right"
|
||||||
|
url="/pages/agreement/privacy/privacy"></u-cell>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<u-modal :show="show" title="请添加客服微信" :closeOnClickOverlay="true" :showCancelButton="true"
|
||||||
|
:showConfirmButton="false" cancelText="关闭" cancelColor="#007aff" @cancel="show = false" @close="show = false">
|
||||||
|
<view class="flex flex-col justify-center items-center" style="width: 80%;">
|
||||||
|
<u-radio-group v-model="chooseCS" placement="column" @change="groupChange">
|
||||||
|
<u-radio :customStyle="{marginBottom: '8px'}" v-for="(item, index) in radiolist" :key="index"
|
||||||
|
:label="item.name" :name="item.name">
|
||||||
|
</u-radio>
|
||||||
|
</u-radio-group>
|
||||||
|
<image style="width: 300upx;height: 300upx;"
|
||||||
|
src="https://ly.imgother.hlh2021.com/1680836523536_小刘客服微信.jpg" mode="aspectFit"></image>
|
||||||
|
<view class="p-20">
|
||||||
|
<view style="color: #646566;font-size: 28upx;">添加请备注自己的用户ID</view>
|
||||||
|
<view style="color: #646566;font-size: 28upx;">截图本页去微信扫码添加</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-modal>
|
||||||
|
|
||||||
|
<u-modal :show="showMini" title="种草短剧小程序" :closeOnClickOverlay="true" :showCancelButton="false"
|
||||||
|
:showConfirmButton="false" @close="showMini = false">
|
||||||
|
<view>
|
||||||
|
<view class="flex flex-col justify-center items-center" style="width: 100%;">
|
||||||
|
<image style="width: 300upx;height: 300upx;"
|
||||||
|
src="https://ly.imgother.hlh2021.com/1680836523536_小刘客服微信.jpg" mode="aspectFit"></image>
|
||||||
|
<view class="p-20">
|
||||||
|
<view style="color: #646566;font-size: 28upx;">截图本页去微信扫码进入小程序</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-modal>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
CTabbar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
chooseCS: '张三',
|
||||||
|
// 基本案列数据
|
||||||
|
radiolist: [{
|
||||||
|
name: '张三',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '李四',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '王五',
|
||||||
|
}, {
|
||||||
|
name: '榴莲',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
showMini: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
groupChange(n) {
|
||||||
|
console.log('groupChange', n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.avatar {
|
||||||
|
width: 140upx;
|
||||||
|
height: 140upx;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 35upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #323333;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-666 {
|
||||||
|
font-size: 30upx;
|
||||||
|
color: #666 !important;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .u-radio-group--column {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.u-radio {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20">
|
||||||
|
<view class="box">
|
||||||
|
<view class="flex flex-col justify-center items-center income">
|
||||||
|
<view>我的收入(元)</view>
|
||||||
|
<view class="number">0.00</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-row three-row">
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<text>邀请人数</text>
|
||||||
|
<text>0</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<text>本月收入</text>
|
||||||
|
<text>0</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<text>上月收入</text>
|
||||||
|
<text>0</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="range">
|
||||||
|
<u-cell title="邀请规则" isLink></u-cell>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="padding: 40upx 20upx;">
|
||||||
|
<u-button shape="circle" type="primary">去邀请</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<u-tabs style="padding: 20upx 0;" :scrollable="false" :list="tabs" lineColor="#007aff" :activeStyle="{
|
||||||
|
color: '#303133',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}" :inactiveStyle="{
|
||||||
|
color: '#606266',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
}" itemStyle="height: 34px; padding-bottom: 10upx;" @change="change">
|
||||||
|
</u-tabs>
|
||||||
|
</view>
|
||||||
|
<view class="content">
|
||||||
|
<view class="table" v-if="currentIndex === 0">
|
||||||
|
<view class="table-line flex flex-row">
|
||||||
|
<view>ID</view>
|
||||||
|
<view>昵称</view>
|
||||||
|
<view>手机号码</view>
|
||||||
|
<view>注册时间</view>
|
||||||
|
</view>
|
||||||
|
<view class="table-line flex flex-row">
|
||||||
|
<view>1</view>
|
||||||
|
<view>张三</view>
|
||||||
|
<view>13547478909</view>
|
||||||
|
<view>2020-10-01</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabs: [{
|
||||||
|
name: '邀请记录'
|
||||||
|
}, {
|
||||||
|
name: '收入记录'
|
||||||
|
}],
|
||||||
|
currentIndex: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
change(e) {
|
||||||
|
this.currentIndex = e.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.box {
|
||||||
|
border-radius: 20upx;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #7a797a;
|
||||||
|
font-size: 30upx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.income {
|
||||||
|
padding: 40upx;
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
color: #363636;
|
||||||
|
font-size: 45upx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.range {
|
||||||
|
border-top: 1upx solid #f6f6f6;
|
||||||
|
}
|
||||||
|
.three-row {
|
||||||
|
padding-bottom: 20upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.table{
|
||||||
|
padding-top: 20upx;
|
||||||
|
}
|
||||||
|
.table-line {
|
||||||
|
width: calc(100vw - 40upx);
|
||||||
|
color: #a6a6a6;
|
||||||
|
font-size: 28upx;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10upx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
view {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
&:first-child {
|
||||||
|
width: 13%;
|
||||||
|
}
|
||||||
|
&:nth-child(2) {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
&:nth-child(3) {
|
||||||
|
width: 37%;
|
||||||
|
}
|
||||||
|
&:nth-child(4) {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .box .u-cell:last-child {
|
||||||
|
.u-line {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="4">
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="flex flex-row justify-center items-center" style="margin-bottom: 50upx;" @click="navigateTo('/pages/my/personal/personal')">
|
||||||
|
<view class="flex justify-center items-center">
|
||||||
|
<image class="avatar" src="../../../static/avatar.png" mode="aspectFit"></image>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1" style="padding-left: 20upx;">
|
||||||
|
<view class="name">{{userInfo.nickName}}</view>
|
||||||
|
<view class="c-666">{{userInfo.phone}}</view>
|
||||||
|
<view class="c-666">ID:{{userInfo.id}}</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-icon name="arrow-right"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="wage p-30 flex flex-col">
|
||||||
|
<view class="flex flex-row">
|
||||||
|
<view class="flex flex-1 flex-col">
|
||||||
|
<view class="wage-tip">可提现金额(元)</view>
|
||||||
|
<view class="money">0.00</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col justify-center">
|
||||||
|
<!-- <view class="wage-tip1 flex flex-row items-center">去提现 <u-icon name="arrow-right" color="#fff" size="13"></u-icon></view>
|
||||||
|
<view class="wage-tip flex flex-row items-center" style="margin-top: 20upx"><u-icon name="info-circle" color="#84b6f9" size="13"></u-icon> 每月15号结算上月订单</view> -->
|
||||||
|
<u-button text="提现" shape="circle" size="small" @click="navigateTo('/pages/my/wallet/wallet')"></u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="flex flex-row">
|
||||||
|
<view class="flex flex-1 flex-col" style="padding: 10upx 0;">
|
||||||
|
<view><text class="wage-tip">总收益</text><text class="nums">0.00</text></view>
|
||||||
|
<view style="padding-top: 20upx"><text class="wage-tip">昨日预估</text><text class="nums">0.00</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-1 flex-col" style="padding: 10upx 0;">
|
||||||
|
<view><text class="wage-tip">七日预估</text><text class="nums">0.00</text></view>
|
||||||
|
<view style="padding-top: 20upx"><text class="wage-tip">本月预估</text><text class="nums">0.00</text></view>
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell class="no-line" title="账号管理" :isLink="true" arrow-direction="right"></u-cell>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell class="no-line" title="邀请好友" :isLink="true" arrow-direction="right" url="/pages/my/inviteFriend/inviteFriend"></u-cell>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell title="客服微信" :isLink="true" arrow-direction="right" @click="show = true"></u-cell>
|
||||||
|
<u-cell class="no-line" title="意见反馈" :isLink="true" arrow-direction="right" url="/pages/my/feedback/feedback"></u-cell>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell title="用户协议" :isLink="true" arrow-direction="right" url="/pages/agreement/user/user"></u-cell>
|
||||||
|
<u-cell title="隐私政策" class="no-line" :isLink="true" arrow-direction="right" url="/pages/agreement/privacy/privacy"></u-cell>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<service-modal :show="show" @close="show = false"></service-modal>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
import serviceModal from '@/components/modal/serviceModal.vue'
|
||||||
|
import { getCustomerList } from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
CTabbar,
|
||||||
|
serviceModal
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
show: false,
|
||||||
|
chooseCS: 0,
|
||||||
|
// 基本案列数据
|
||||||
|
radiolist: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// onShow() {
|
||||||
|
// this.getServiceList()
|
||||||
|
// },
|
||||||
|
// methods: {
|
||||||
|
// async getServiceList() {
|
||||||
|
// const res = await getCustomerList({})
|
||||||
|
// this.radiolist = res.data
|
||||||
|
// this.chooseCS = 0
|
||||||
|
// },
|
||||||
|
// groupChange(n) {
|
||||||
|
// this.chooseCS = n
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.avatar {
|
||||||
|
width: 140upx;
|
||||||
|
height: 140upx;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
font-size: 35upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #323333;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
.c-666 {
|
||||||
|
font-size: 30upx;
|
||||||
|
color: #666!important;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
.wage {
|
||||||
|
background-color: $uni-theme;
|
||||||
|
border-radius: 20upx;
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
.wage-tip {
|
||||||
|
color: #84b6f9;
|
||||||
|
}
|
||||||
|
.wage-tip1 {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.money {
|
||||||
|
color: #f4f8ff;
|
||||||
|
font-size: 50upx;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-top: 15upx;
|
||||||
|
padding-bottom: 30upx;
|
||||||
|
}
|
||||||
|
.nums {
|
||||||
|
color: #f4f8ff;
|
||||||
|
margin-left: 15upx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20">
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell title="我的昵称" :value="userInfo.nickName"></u-cell>
|
||||||
|
<u-cell title="我的手机号" :value="userInfo.phone"></u-cell>
|
||||||
|
<u-cell title="我的ID" :value="userInfo.id"></u-cell>
|
||||||
|
<u-cell title="我的微信" :value="userInfo.openId ? '已绑定' : '未绑定'" :isLink="true" arrow-direction="right"></u-cell>
|
||||||
|
</view>
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell title="登录密码" :isLink="true" arrow-direction="right" :url="'/pages/login/forgetPwd/forgetPwd?phone='+userInfo.phone"></u-cell>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="height: 50upx;"></view>
|
||||||
|
<u-button type="default" :plain="true" shape="circle" text="退出登录" color="red" throttleTime="200" :customStyle="{border: 'none'}"></u-button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
<template>
|
||||||
|
<view class="container p-30">
|
||||||
|
<view class="p1">修改密码</view>
|
||||||
|
<view class="c-menu p-r-20">
|
||||||
|
<u--form labelPosition="left" ref="uForm">
|
||||||
|
<u-form-item borderBottom>
|
||||||
|
<u--input value="1529238591" border="none" readonly></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom>
|
||||||
|
<u-input v-model="form.code" border="none" placeholder="请输入验证码" clearable>
|
||||||
|
<template slot="suffix">
|
||||||
|
<u-code ref="uCode" @change="codeChange" seconds="20" @start="disabled1 = true"
|
||||||
|
@end="disabled1 = false"></u-code>
|
||||||
|
<u-button @tap="getCode" :text="tips" type="primary" size="mini"
|
||||||
|
:disabled="disabled1"></u-button>
|
||||||
|
</template>
|
||||||
|
</u-input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom>
|
||||||
|
<u-input v-model="form.password" border="none" password type="password" clearable
|
||||||
|
placeholder="请输入密码" />
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom>
|
||||||
|
<u-input v-model="form.rePassword" border="none" password type="password" clearable
|
||||||
|
placeholder="请输入确认密码" />
|
||||||
|
</u-form-item>
|
||||||
|
</u--form>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="padding: 50rpx;">
|
||||||
|
<u-button shape="circle" type="primary">提交</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
code: ''
|
||||||
|
},
|
||||||
|
disabled1: false,
|
||||||
|
tips: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
codeChange(text) {
|
||||||
|
this.tips = text;
|
||||||
|
},
|
||||||
|
getCode() {
|
||||||
|
if (this.$refs.uCode.canGetCode) {
|
||||||
|
// 模拟向后端请求验证码
|
||||||
|
uni.showLoading({
|
||||||
|
title: '正在获取验证码'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
// 这里此提示会被this.start()方法中的提示覆盖
|
||||||
|
uni.$u.toast('验证码已发送');
|
||||||
|
// 通知验证码组件内部开始倒计时
|
||||||
|
this.$refs.uCode.start();
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
uni.$u.toast('倒计时结束后再发送');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
.p1 {
|
||||||
|
color: #323333;
|
||||||
|
font-size: 40upx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="c-menu p-r-20">
|
||||||
|
<u--form labelPosition="left" labelWidth="100" ref="uForm">
|
||||||
|
<u-form-item borderBottom label="实名姓名">
|
||||||
|
<u--input border="none" placeholder="请输入(必填)" v-model="form.realName"></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom label="账号">
|
||||||
|
<u--input border="none" placeholder="请输入(必填)" v-model="form.zfbAccount"></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
</u--form>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="padding: 50rpx 30upx;position: fixed;left: 0;bottom: 0;width: 100%;box-sizing: border-box;">
|
||||||
|
<u-button shape="circle" type="primary">提交</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
zfbAccount: '',
|
||||||
|
realName: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="c-menu p-r-20">
|
||||||
|
<u--form labelPosition="left" labelWidth="100" ref="uForm">
|
||||||
|
<u-form-item borderBottom label="收款户名">
|
||||||
|
<u--input border="none" placeholder="请输入(必填)" v-model="form.bankCardAccountName"></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom label="银行名称">
|
||||||
|
<picker @change="bindPickerChange" :value="chooseBank" :range="bankList">
|
||||||
|
<view style="color: #303133;">{{ chooseBank === null ? '请选择银行' : bankList[chooseBank] }}</view>
|
||||||
|
</picker>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom label="支行所在地">
|
||||||
|
<!-- <u--input border="none" placeholder="请选择" v-model="form.bankCardArea"></u--input> -->
|
||||||
|
<view style="color: #303133;" @click="visible = true">
|
||||||
|
{{ !form.bankCardArea ? '请选择支行所在地' : form.bankCardArea }}</view>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom label="支行名称">
|
||||||
|
<u--input border="none" placeholder="请输入(必填)" v-model="form.bankCardSubBranchName"></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom label="银行卡号">
|
||||||
|
<u--input border="none" placeholder="请输入(必填)" v-model="form.bankCardNumber"></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item borderBottom label="确认卡号">
|
||||||
|
<u--input border="none" placeholder="请输入(必填)" v-model="form.reBankCardNumber"></u--input>
|
||||||
|
</u-form-item>
|
||||||
|
</u--form>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="padding: 50rpx 30upx;position: fixed;left: 0;bottom: 0;width: 100%;box-sizing: border-box;">
|
||||||
|
<u-button shape="circle" type="primary" @click="submit">提交</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<cityPicker column="3" :default-value="defaultValue" :mask-close-able="maskCloseAble" @confirm="confirm"
|
||||||
|
@cancel="cancel" :visible="visible" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import cityPicker from '@/uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/piaoyi-cityPicker'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
cityPicker
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
bankCardAccountName: '',
|
||||||
|
bankCardArea: '',
|
||||||
|
bankCardNumber: '',
|
||||||
|
reBankCardNumber: '',
|
||||||
|
bankCardSubBranchName: '',
|
||||||
|
bankCardType: ''
|
||||||
|
},
|
||||||
|
bankList: [
|
||||||
|
'农业银行',
|
||||||
|
'建设银行',
|
||||||
|
'工商银行',
|
||||||
|
'交通银行',
|
||||||
|
'中国银行'
|
||||||
|
],
|
||||||
|
chooseBank: null,
|
||||||
|
visible: false,
|
||||||
|
maskCloseAble: true,
|
||||||
|
defaultValue: '110101',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
confirm(val) {
|
||||||
|
console.log(val);
|
||||||
|
this.form.bankCardArea = val.name
|
||||||
|
this.visible = false
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
this.visible = false
|
||||||
|
},
|
||||||
|
bindPickerChange(e) {
|
||||||
|
this.chooseBank = parseInt(e.detail.value)
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
if(!this.form.bankCardAccountName) return uni.$u.toast('请输入您的收款账户')
|
||||||
|
if(!this.form.bankCardType) return uni.$u.toast('请选择银行')
|
||||||
|
if(!this.form.bankCardArea) return uni.$u.toast('请选择支行所在地区')
|
||||||
|
if(!this.form.bankCardSubBranchName) return uni.$u.toast('请输入支行名称')
|
||||||
|
if(!this.form.bankCardNumber) return uni.$u.toast('请输入银行卡号')
|
||||||
|
if(!this.form.reBankCardNumber) return uni.$u.toast('请再次输入银行卡号')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20">
|
||||||
|
<view class="p-30 bg-white wage">
|
||||||
|
<view>可提现总金额(元)</view>
|
||||||
|
<view class="money">0.00</view>
|
||||||
|
<view class="btn-wrap">
|
||||||
|
<u-button shape="circle" type="primary" size="small">立即提现</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="c-menu">
|
||||||
|
<u-cell title="提现银行卡" isLink @click="bindBank">
|
||||||
|
<template slot="value">
|
||||||
|
<text v-if="walletInfo.bankCardNumber" style="color: #007aff;">已绑定</text>
|
||||||
|
<text v-else>未绑定</text>
|
||||||
|
</template>
|
||||||
|
</u-cell>
|
||||||
|
<u-cell title="提现支付宝" isLink @click="bindAlipay">
|
||||||
|
<template slot="value">
|
||||||
|
<text v-if="walletInfo.zfbAccount" style="color: #007aff;">已绑定</text>
|
||||||
|
<text v-else>未绑定</text>
|
||||||
|
</template>
|
||||||
|
</u-cell>
|
||||||
|
<u-cell title="提现记录" isLink url="/pages/my/wallet/withdrawalRecord/withdrawalRecord"></u-cell>
|
||||||
|
<u-cell class="no-line" title="资金记录" isLink></u-cell>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- <view class="c-menu">
|
||||||
|
<u-cell class="no-line" title="开票信息" isLink></u-cell>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { withdraw } from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
walletInfo: {
|
||||||
|
bankCardAccountName: '',
|
||||||
|
bankCardArea: '',
|
||||||
|
bankCardNumber: '',
|
||||||
|
bankCardSubBranchName: '',
|
||||||
|
bankCardType: '',
|
||||||
|
realName: '',
|
||||||
|
zfbAccount: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
this.getInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getInfo() {
|
||||||
|
await withdraw.getInfo({userId: this.userInfo.id})
|
||||||
|
},
|
||||||
|
bindBank() {
|
||||||
|
if(this.walletInfo.bankCardNumber) return
|
||||||
|
this.navigateTo('/pages/my/wallet/bindBankCard/bindBankCard')
|
||||||
|
},
|
||||||
|
bindAlipay() {
|
||||||
|
if(this.walletInfo.zfbAccount) return
|
||||||
|
this.navigateTo('/pages/my/wallet/bindAlipay/bindAlipay')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wage {
|
||||||
|
border-radius: 20upx;
|
||||||
|
color: #6c6c6c;
|
||||||
|
font-size: 30upx;
|
||||||
|
.money {
|
||||||
|
font-size: 50upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
padding: 20upx 0;
|
||||||
|
}
|
||||||
|
.btn-wrap {
|
||||||
|
width: 150upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="item flex justify-between">
|
||||||
|
<view class="flex-1">
|
||||||
|
<view>提现项目:123</view>
|
||||||
|
<view>提现金额:200</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col justify-between">
|
||||||
|
<view class="status1">提现中</view>
|
||||||
|
<view class="time">2020-11-11</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item flex justify-between">
|
||||||
|
<view class="flex-1">
|
||||||
|
<view>提现项目:123</view>
|
||||||
|
<view>提现金额:200</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col justify-between">
|
||||||
|
<view class="status2">成功</view>
|
||||||
|
<view class="time">2020-11-11</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item flex justify-between">
|
||||||
|
<view class="flex-1">
|
||||||
|
<view>提现项目:123</view>
|
||||||
|
<view>提现金额:200</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col justify-between">
|
||||||
|
<view class="status3">失败</view>
|
||||||
|
<view class="time">2020-11-11</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.item {
|
||||||
|
border-radius: 20upx;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20upx;
|
||||||
|
color: rgb(102, 102, 102);
|
||||||
|
margin-bottom: 20upx;
|
||||||
|
font-size: 30upx;
|
||||||
|
.flex-1 view {
|
||||||
|
padding: 5upx 0;
|
||||||
|
}
|
||||||
|
.time {
|
||||||
|
font-size: 23upx;
|
||||||
|
}
|
||||||
|
.status1 {
|
||||||
|
color: #3c9cff;
|
||||||
|
}
|
||||||
|
.status2 {
|
||||||
|
color: #5ac725;
|
||||||
|
}
|
||||||
|
.status3 {
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20" v-if="info">
|
||||||
|
<view class="create-time">发布时间:{{info.updateTime}}</view>
|
||||||
|
<view class="content">{{info.detail}}</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
info: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(option) {
|
||||||
|
this.info = JSON.parse(option.item)
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: this.info.title
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.create-time {
|
||||||
|
font-size: 25upx;
|
||||||
|
color: #666;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
font-size: 23upx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
|
||||||
|
<view class="context">
|
||||||
|
<u-cell-group>
|
||||||
|
<u-cell v-for="item in list" :key="item.id" isLink :title="item.title" @click="routeInfo(item)"></u-cell>
|
||||||
|
</u-cell-group>
|
||||||
|
</view>
|
||||||
|
</mescroll-body>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getMessagePage } from '@/api/index.js'
|
||||||
|
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||||
|
export default {
|
||||||
|
mixins: [MescrollMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
routeInfo(item) {
|
||||||
|
this.navigateTo('/pages/notice/info/info?item='+JSON.stringify(item))
|
||||||
|
},
|
||||||
|
async getList(pageNum) {
|
||||||
|
const res = await getMessagePage(pageNum, 15, {})
|
||||||
|
if(res.success) {
|
||||||
|
this.mescroll.endBySize(res.data.list.length, parseInt(res.data.total));
|
||||||
|
if (pageNum == 1) this.list = []; //如果是第一页需手动制空列表
|
||||||
|
this.list = this.list.concat(res.data.list);
|
||||||
|
} else {
|
||||||
|
this.mescroll.endErr();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upCallback(page) {
|
||||||
|
this.getList(page.num)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.context {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<u--form :model="form" :rules="rules" ref="uForm" labelWidth="80">
|
||||||
|
<u-form-item label="账户名" prop="nickName">
|
||||||
|
<u-input v-model="form.nickName" placeholder="请输入账户名" clearable />
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item label="手机号" prop="phone">
|
||||||
|
<u-input v-model="form.phone" placeholder="请输入手机号" clearable />
|
||||||
|
</u-form-item>
|
||||||
|
<!-- <u-form-item label="验证码" prop="code" labelWidth="80" borderBottom>
|
||||||
|
<u-input v-model="form.code" placeholder="请填写验证码" clearable>
|
||||||
|
<template slot="suffix">
|
||||||
|
<u-code ref="uCode" @change="codeChange" seconds="20" @start="disabled1 = true"
|
||||||
|
@end="disabled1 = false"></u-code>
|
||||||
|
<u-button @tap="getCode" :text="tips" type="primary" size="mini"
|
||||||
|
:disabled="disabled1"></u-button>
|
||||||
|
</template>
|
||||||
|
</u-input>
|
||||||
|
</u-form-item> -->
|
||||||
|
<u-form-item label="密码" prop="password">
|
||||||
|
<u-input v-model="form.password" password type="password" clearable placeholder="请输入密码" />
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item label="确认密码" prop="rePassword">
|
||||||
|
<u-input v-model="form.rePassword" password type="password" clearable placeholder="请再次输入密码" />
|
||||||
|
</u-form-item>
|
||||||
|
<u-form-item label="渠道码" prop="agencyId">
|
||||||
|
<u-input v-model="form.agencyId" placeholder="请输入渠道码" clearable />
|
||||||
|
</u-form-item>
|
||||||
|
</u--form>
|
||||||
|
<view style="padding: 50rpx;">
|
||||||
|
<u-button shape="circle" type="primary" @click="submit">进入</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
updateUserById
|
||||||
|
} from '@/api/index.js'
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from 'vuex'
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
...mapState(['userInfo'])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
disabled1: false,
|
||||||
|
tips: '',
|
||||||
|
form: {
|
||||||
|
nickName: '',
|
||||||
|
phone: '',
|
||||||
|
code: '',
|
||||||
|
agencyId: '',
|
||||||
|
password: '',
|
||||||
|
rePassword: ''
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
nickName: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入账户名',
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}],
|
||||||
|
// 字段名称
|
||||||
|
phone: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入手机号',
|
||||||
|
trigger: ['change', 'blur'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 自定义验证函数,见上说明
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
// uni.$u.test.mobile()就是返回true或者false的
|
||||||
|
return uni.$u.test.mobile(value);
|
||||||
|
},
|
||||||
|
message: '手机号码不正确',
|
||||||
|
trigger: ['change', 'blur'],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
code: {
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
len: 6,
|
||||||
|
message: '请填写6位验证码',
|
||||||
|
trigger: ['blur']
|
||||||
|
},
|
||||||
|
password: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入密码',
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}],
|
||||||
|
rePassword: [{
|
||||||
|
required: true,
|
||||||
|
message: '请再次输入密码',
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (!this.userInfo) {
|
||||||
|
uni.reLaunch({
|
||||||
|
// #ifdef H5
|
||||||
|
url: '/pages/login/login',
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
url: '/pages/entry/entry'
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
//如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则。
|
||||||
|
this.$refs.uForm.setRules(this.rules)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit() {
|
||||||
|
this.$refs.uForm.validate().then(async res => {
|
||||||
|
if (this.form.password !== this.form.rePassword) {
|
||||||
|
return uni.$u.toast('两次密码不一致,请重新输入')
|
||||||
|
}
|
||||||
|
const res1 = await updateUserById({
|
||||||
|
...this.userInfo,
|
||||||
|
...this.form
|
||||||
|
})
|
||||||
|
if (!res1.success) return
|
||||||
|
uni.showToast({
|
||||||
|
title: '操作成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
success() {
|
||||||
|
uni.reLaunch({
|
||||||
|
// #ifdef H5
|
||||||
|
url: '/pages/home/h5/h5',
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
url: '/pages/home/mini/mini'
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch(errors => {
|
||||||
|
// uni.$u.toast('校验失败')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
codeChange(text) {
|
||||||
|
this.tips = text;
|
||||||
|
},
|
||||||
|
getCode() {
|
||||||
|
if (this.$refs.uCode.canGetCode) {
|
||||||
|
// 模拟向后端请求验证码
|
||||||
|
uni.showLoading({
|
||||||
|
title: '正在获取验证码'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
// 这里此提示会被this.start()方法中的提示覆盖
|
||||||
|
uni.$u.toast('验证码已发送');
|
||||||
|
// 通知验证码组件内部开始倒计时
|
||||||
|
this.$refs.uCode.start();
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
uni.$u.toast('倒计时结束后再发送');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.container {
|
||||||
|
padding: 30rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20">
|
||||||
|
<view>
|
||||||
|
<view class="information p-20 flex flex-row">
|
||||||
|
<image class="img" src="" mode="widthFix"></image>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="title">老公的金丝雀怀孕后</text>
|
||||||
|
<text>共73集 已完结</text>
|
||||||
|
<text>视频号 森林微剧</text>
|
||||||
|
<text>2024-03-04 上线</text>
|
||||||
|
<text>已有 100人推广</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="way-percent flex flex-row">
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<view class="biger">CPS</view>
|
||||||
|
<view class="smaller">分成方式</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<view class="biger">75%</view>
|
||||||
|
<view class="smaller">分成比例</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="info">
|
||||||
|
<u-tabs style="padding: 20upx 0;" :scrollable="false" :list="tabs" lineColor="#007aff" :activeStyle="{
|
||||||
|
color: '#303133',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}" :inactiveStyle="{
|
||||||
|
color: '#606266',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
}" itemStyle="height: 34px; padding-bottom: 10upx;" @change="change">
|
||||||
|
</u-tabs>
|
||||||
|
<view class="inside-content" v-if="currentIndex === 0">
|
||||||
|
<text>链接:https://pan.baidu.com/s/1vqFyozWUCc5NSYdqIqcP2A?pwd=uye7</text>
|
||||||
|
<view class="copy-wrap"><text class="copy">复制链接</text></view>
|
||||||
|
</view>
|
||||||
|
<view class="imageine" v-else-if="currentIndex === 1">
|
||||||
|
暂无信息
|
||||||
|
</view>
|
||||||
|
<view class="imageine" v-else-if="currentIndex === 2">
|
||||||
|
暂无信息
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fix-btn p-20">
|
||||||
|
<u-button shape="circle" type="primary" @click="showPromotion = true">创建推广</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<u-modal :show="showPromotion" :closeOnClickOverlay="true" :showCancelButton="true" cancelText="关闭"
|
||||||
|
cancelColor="#007aff" :showConfirmButton="false" @close="showPromotion = false;promotionActive=0;" @cancel="showPromotion = false;promotionActive=0;">
|
||||||
|
<view style="width: 100%;">
|
||||||
|
<view class="flex flex-col justify-center items-center" style="width: 100%;">
|
||||||
|
<u-tabs
|
||||||
|
v-if="showPromotion"
|
||||||
|
:scrollable="!isH5"
|
||||||
|
:list="tabs2" lineColor="#007aff" :activeStyle="{
|
||||||
|
color: '#303133',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}" :inactiveStyle="{
|
||||||
|
color: '#606266',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
}" itemStyle="height: 34px; padding-bottom: 10upx;" class="tabs2" @change="change2">
|
||||||
|
</u-tabs>
|
||||||
|
<view class="promotion" v-if="promotionActive === 0">
|
||||||
|
<c-popover placement="bottom-start" ref="Popover1" class="item-popover">
|
||||||
|
<view slot="content"
|
||||||
|
style="width: 250upx;padding: 15upx;font-size: 26upx;color: rgb(50, 50, 51);">
|
||||||
|
海报可用于在小红书、多多视频、皮皮虾、腾讯视频等平台发布短剧内容,在评论区放置海报,引流到微信进行变现。</view>
|
||||||
|
<view class="use-way flex flex-row items-center"><text
|
||||||
|
style="padding-right: 10upx;">使用说明</text><u-icon size="15"
|
||||||
|
name="question-circle"></u-icon></view>
|
||||||
|
</c-popover>
|
||||||
|
|
||||||
|
<view style="padding-top: 20upx;">
|
||||||
|
<u-swiper :list="list6" @change="e => currentNum = e.current" :autoplay="false"
|
||||||
|
indicatorStyle="right: 20px">
|
||||||
|
<view slot="indicator" class="indicator">
|
||||||
|
<view class="indicator__dot" v-for="(item, index) in list6" :key="index"
|
||||||
|
:class="[index === currentNum && 'indicator__dot--active']">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-swiper>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="p-30 flex flex-row justify-center" style="padding-bottom: 0upx;">
|
||||||
|
<u-button type="primary" size="small" color="#007aff" :plain="true" :hairline="true" icon="share"
|
||||||
|
text="保存海报"></u-button>
|
||||||
|
<view style="width: 40upx;"></view>
|
||||||
|
<u-button color="#007aff" type="primary" size="small" :plain="true"
|
||||||
|
:hairline="true" icon="attach" text="复制链接"></u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="promotionActive === 1">
|
||||||
|
<view class="content-url">https://kzurl05.cn/7GXLRU</view>
|
||||||
|
<view class="p-d-20 flex flex-row justify-center">
|
||||||
|
<view style="width: 170upx;">
|
||||||
|
<u-button color="#007aff" type="primary" size="small" :plain="true"
|
||||||
|
:hairline="true" icon="attach" text="复制链接"></u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-modal>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import cPopover from '@/uni_modules/zb-popover/components/zb-popover/zb-popover.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
cPopover
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabs: [{
|
||||||
|
name: '视频素材'
|
||||||
|
}, {
|
||||||
|
name: '创作灵感'
|
||||||
|
}, {
|
||||||
|
name: '挂载流程'
|
||||||
|
}],
|
||||||
|
tabs2: [{
|
||||||
|
name: '私域推广'
|
||||||
|
}, {
|
||||||
|
name: '视频号推广'
|
||||||
|
}],
|
||||||
|
promotionActive: 0,
|
||||||
|
currentIndex: 0,
|
||||||
|
showPromotion: false,
|
||||||
|
list6: [
|
||||||
|
'https://cdn.uviewui.com/uview/swiper/swiper2.png',
|
||||||
|
'https://cdn.uviewui.com/uview/swiper/swiper3.png',
|
||||||
|
'https://cdn.uviewui.com/uview/swiper/swiper1.png',
|
||||||
|
],
|
||||||
|
currentNum: 0,
|
||||||
|
isH5: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// #ifdef H5
|
||||||
|
this.isH5 = true
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
change(e) {
|
||||||
|
this.currentIndex = e.index
|
||||||
|
},
|
||||||
|
change2(e) {
|
||||||
|
this.promotionActive = e.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.fix-btn {
|
||||||
|
width: 100vw;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.information {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 150upx;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 10upx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
padding-left: 20upx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #323333;
|
||||||
|
font-size: 32upx;
|
||||||
|
font-weight: 550;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 25upx;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.way-percent {
|
||||||
|
padding: 30upx 0;
|
||||||
|
background: #f3f4f6;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 0 0 20upx 20upx;
|
||||||
|
border-top: 0;
|
||||||
|
|
||||||
|
.biger {
|
||||||
|
font-size: 35upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #323333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smaller {
|
||||||
|
font-size: 28upx;
|
||||||
|
color: #7d8394;
|
||||||
|
margin-top: 10upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
margin-top: 30upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inside-content {
|
||||||
|
font-size: 28upx;
|
||||||
|
padding: 30upx;
|
||||||
|
color: #666;
|
||||||
|
word-break: break-all;
|
||||||
|
border-top: 1upx solid #ebedf0;
|
||||||
|
|
||||||
|
.copy-wrap {
|
||||||
|
padding-top: 50upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
color: $uni-theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageine {
|
||||||
|
font-size: 28upx;
|
||||||
|
padding: 30upx;
|
||||||
|
color: #666;
|
||||||
|
word-break: break-all;
|
||||||
|
border-top: 1upx solid #ebedf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
right: 0 !important;
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
height: 6px;
|
||||||
|
width: 6px;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.35);
|
||||||
|
margin: 0 5px;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.promotion {
|
||||||
|
width: 90%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 40upx;
|
||||||
|
background: #f7f8fa;
|
||||||
|
margin-top: 30upx;
|
||||||
|
|
||||||
|
.use-way {
|
||||||
|
color: #646566;
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-url {
|
||||||
|
margin: 20upx 0;
|
||||||
|
width: 500upx;
|
||||||
|
height: 300upx;
|
||||||
|
padding: 20upx;
|
||||||
|
border-radius: 20upx;
|
||||||
|
border: 2upx solid #eee;
|
||||||
|
word-break: break-all;
|
||||||
|
color: #646566;
|
||||||
|
font-size: 30upx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs2 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
::v-deep .copy2 {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
::v-deep .copy1 {
|
||||||
|
margin-left: 40upx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,341 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="1">
|
||||||
|
<view>
|
||||||
|
<view class="p-30">
|
||||||
|
<view class="type-change">
|
||||||
|
<view class="item flex flex-col justify-center items-center" :class="{active: type == 1}"
|
||||||
|
@click="changeType(1)">
|
||||||
|
<text class="t1">短剧列表</text>
|
||||||
|
<text class="t2">多平台 多剧场变现</text>
|
||||||
|
</view>
|
||||||
|
<view class="item flex flex-col justify-center items-center" :class="{active: type == 2}"
|
||||||
|
@click="changeType(2)">
|
||||||
|
<text class="t1">我的推广</text>
|
||||||
|
<text class="t2">推广链接再次使用</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view style="padding-top: 50upx;">
|
||||||
|
<u-search v-model="keyword" :show-action="false" borderColor="#fff"
|
||||||
|
bgColor="#fff" placeholder="请输入剧名" @search="search"></u-search>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-tabs style="padding: 20upx 0;" :list="tabs" lineWidth="30" lineColor="#007aff" :activeStyle="{
|
||||||
|
color: '#303133',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
transform: 'scale(1.05)'
|
||||||
|
}" :inactiveStyle="{
|
||||||
|
color: '#606266',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
}" itemStyle="padding-left: 15px; padding-right: 15px; height: 34px;" @change="changeTab">
|
||||||
|
</u-tabs>
|
||||||
|
<view class="search-box">
|
||||||
|
<sl-filter style="border-radius: 30upx 30upx 0 0;" :ref="'slFilter'" :topFixed="false"
|
||||||
|
:isTransNav="true" :navHeight="0" :color="titleColor" :themeColor="themeColor"
|
||||||
|
:menuList="menuList" @result="result"></sl-filter>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
|
||||||
|
<view class="search-result">
|
||||||
|
<view class="search-item" v-for="item in list" :key="item.id">
|
||||||
|
<view class="img-wrap" @click.stop="navigateTo('/pages/shortPlay/info/info')">
|
||||||
|
<text class="label">{{sourceType[item.sourceType]}}</text>
|
||||||
|
<view class="type flex flex-row items-center justify-center"><u-icon name="attach" color="#ffffffd9"></u-icon>{{item.itemTypeName}}</view>
|
||||||
|
<image :src="item.coverPic" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="content-wrap">
|
||||||
|
<view class="name ellipsis">{{item.videoName}}</view>
|
||||||
|
<view class="desc">{{item.completeNot ? '未完结' : '已完结'}} 共{{item.numberEpisode}}集</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="search-item">
|
||||||
|
<view class="img-wrap">
|
||||||
|
<text class="label">快手</text>
|
||||||
|
<view class="type flex flex-row items-center justify-center"><u-icon name="attach" color="#ffffffd9"></u-icon>红火剧场</view>
|
||||||
|
<image src="https://resali.ssread.cn/cppartner/4x1/41x0/410x0/41000102244/41000102244.jpg?t=1708324420602" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="content-wrap">
|
||||||
|
<view class="name ellipsis">下山后我被美女包围了</view>
|
||||||
|
<view class="desc">已完结 共17集</view>
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</mescroll-body>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
import slFilter from '@/components/sl-filter/sl-filter.vue';
|
||||||
|
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||||
|
import { getItemList, getTypeList } from '@/api/index.js'
|
||||||
|
import { currentDate } from '@/utils/common.js'
|
||||||
|
export default {
|
||||||
|
mixins: [MescrollMixin],
|
||||||
|
components: {
|
||||||
|
CTabbar,
|
||||||
|
slFilter
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
type: 1,
|
||||||
|
keyword: '',
|
||||||
|
tabs: [{
|
||||||
|
name: '全部'
|
||||||
|
}, {
|
||||||
|
name: '抖音'
|
||||||
|
}, {
|
||||||
|
name: '快手'
|
||||||
|
}, {
|
||||||
|
name: '视频号'
|
||||||
|
}],
|
||||||
|
themeColor: '#007aff',
|
||||||
|
titleColor: '#666666',
|
||||||
|
filterResult: '',
|
||||||
|
menuList: [{
|
||||||
|
'title': '剧方筛选',
|
||||||
|
'isMutiple': false,
|
||||||
|
'key': 'playSource',
|
||||||
|
'detailList': []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': '上架时间',
|
||||||
|
'key': 'date',
|
||||||
|
'isSort': true,
|
||||||
|
'reflexTitle': true,
|
||||||
|
'detailList': [{
|
||||||
|
'title': '默认时间',
|
||||||
|
'value': ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': '7天',
|
||||||
|
'value': '7'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': '15天',
|
||||||
|
'value': '15'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': '30天',
|
||||||
|
'value': '30'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'title': '半年',
|
||||||
|
'value': '180'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
list: [],
|
||||||
|
sourceType: {
|
||||||
|
'1': '抖音',
|
||||||
|
'2': '快手',
|
||||||
|
'3': '视频号'
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
sourceType: '',
|
||||||
|
itemType: '',
|
||||||
|
createBeginTime: '',
|
||||||
|
createEndTime: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getPlayType()
|
||||||
|
console.log(currentDate(), currentDate(false, -7));
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getPlayType() {
|
||||||
|
const res = await getTypeList({})
|
||||||
|
const getData = res.data.map(i => {
|
||||||
|
return {
|
||||||
|
title: i.name,
|
||||||
|
value: i.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.menuList[0].detailList = [
|
||||||
|
{
|
||||||
|
'title': '全部剧方',
|
||||||
|
'value': ''
|
||||||
|
},
|
||||||
|
...getData
|
||||||
|
]
|
||||||
|
},
|
||||||
|
changeType(type) {
|
||||||
|
this.type = type
|
||||||
|
},
|
||||||
|
result(val) {
|
||||||
|
this.filter.itemType = val.playSource
|
||||||
|
if(val.date) {
|
||||||
|
this.filter.createBeginTime = currentDate(false, -parseInt(val.date)) + ' 00:00:00'
|
||||||
|
this.filter.createEndTime = currentDate() + ' 00:00:00'
|
||||||
|
} else {
|
||||||
|
this.filter.createBeginTime = '';
|
||||||
|
this.filter.createEndTime = '';
|
||||||
|
}
|
||||||
|
this.search()
|
||||||
|
},
|
||||||
|
changeTab(e){
|
||||||
|
this.filter.sourceType = e.index ? e.index : ''
|
||||||
|
this.search()
|
||||||
|
},
|
||||||
|
search(){
|
||||||
|
this.list = [];
|
||||||
|
this.mescroll.resetUpScroll();
|
||||||
|
},
|
||||||
|
async getList(pageNum) {
|
||||||
|
const res = await getItemList(pageNum, 10, {
|
||||||
|
...this.filter,
|
||||||
|
videoName: this.keyword
|
||||||
|
})
|
||||||
|
if(res.success) {
|
||||||
|
this.mescroll.endBySize(res.data.list.length, parseInt(res.data.total));
|
||||||
|
if (pageNum == 1) this.list = []; //如果是第一页需手动制空列表
|
||||||
|
this.list = this.list.concat(res.data.list);
|
||||||
|
} else {
|
||||||
|
this.mescroll.endErr();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upCallback(page) {
|
||||||
|
this.getList(page.num)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.type-change {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 335upx;
|
||||||
|
padding: 40upx;
|
||||||
|
border-radius: 20upx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -40upx;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -15upx;
|
||||||
|
border-top: 30upx solid transparent;
|
||||||
|
border-left: 30upx solid transparent;
|
||||||
|
border-right: 30upx solid transparent;
|
||||||
|
border-bottom: 30upx solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
background-color: #eceefb;
|
||||||
|
color: #071e7a;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $uni-theme;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
border-top: 30upx solid $uni-theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
background-color: #fee8e8;
|
||||||
|
color: #b5615e;
|
||||||
|
margin-left: 20upx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #fe6767;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
border-top: 30upx solid #fe6767;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.t1 {
|
||||||
|
font-size: 40upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t2 {
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
background-image: linear-gradient(180deg, #fff 0, rgba(255, 255, 255, 0) 100%);
|
||||||
|
border-radius: 30upx 30upx 0 0;
|
||||||
|
height: 100upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result {
|
||||||
|
padding: 0 30upx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
.search-item {
|
||||||
|
width: 216.66upx;
|
||||||
|
margin-right: 20upx;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 15upx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 20upx;
|
||||||
|
&:nth-child(3n) {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.img-wrap {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.label{
|
||||||
|
border-radius: 15upx 0 15upx 0;
|
||||||
|
background: $uni-theme;
|
||||||
|
color: #fff;
|
||||||
|
padding: 10upx 15upx;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
.type {
|
||||||
|
border-radius: 5upx;
|
||||||
|
background: rgba(0,0,0,.55);
|
||||||
|
color: rgba(255,255,255,.85);
|
||||||
|
padding: 8upx 10upx;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20upx;
|
||||||
|
left: 10upx;
|
||||||
|
z-index: 1;
|
||||||
|
font-size: 22upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content-wrap {
|
||||||
|
padding: 10upx 15upx;
|
||||||
|
padding-bottom: 20upx;
|
||||||
|
.name {
|
||||||
|
color: #323333;
|
||||||
|
font-size: 28upx;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
color: #999;
|
||||||
|
font-size: 25upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<template>
|
||||||
|
<view></view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
uni.reLaunch({
|
||||||
|
// #ifdef H5
|
||||||
|
url: uni.getStorageSync("token") ? '/pages/home/h5/h5' : '/pages/login/login',
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
// url: '/pages/home/mini/mini',
|
||||||
|
url: '/pages/my/mini/mini',
|
||||||
|
// url: '/pages/login/forgetPwd/forgetPwd',
|
||||||
|
// url: uni.getStorageSync("token") ? '/pages/my/mini/mini' : '/pages/entry/entry',
|
||||||
|
// #endif
|
||||||
|
success() {
|
||||||
|
uni.hideTabBar()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,204 @@
|
||||||
|
<template>
|
||||||
|
<view class="p-20">
|
||||||
|
<view>
|
||||||
|
<view class="top-img flex justify-center items-center">
|
||||||
|
<image src="../../../static/uni.png" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="information p-20 flex flex-row">
|
||||||
|
<image class="img" src="../../../static/uni.png" mode="aspectFit"></image>
|
||||||
|
<view class="flex-1 flex flex-col">
|
||||||
|
<text class="title">老公的金丝雀怀孕后</text>
|
||||||
|
<text>抖音 | CPM</text>
|
||||||
|
<text>地球行者品宣部</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="way-percent flex flex-row">
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<view class="biger">52</view>
|
||||||
|
<view class="smaller">视频数</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<view class="biger">3.22w</view>
|
||||||
|
<view class="smaller">播放次数</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<view class="biger">217</view>
|
||||||
|
<view class="smaller">获赞数</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col justify-center items-center">
|
||||||
|
<view class="biger">42</view>
|
||||||
|
<view class="smaller">评论数</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="p-30 bg-white introduce">
|
||||||
|
<view>任务奖励:根据视频表现持续瓜分现金,先到先得</view>
|
||||||
|
<view>总奖金池:<text style="color: red;">1,0000.00</text></view>
|
||||||
|
<view>
|
||||||
|
<text>奖励已瓜分</text>
|
||||||
|
<cmd-progress :percent="16"></cmd-progress>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="info">
|
||||||
|
<u-tabs style="padding: 20upx 0;" :scrollable="false" :list="tabs" lineColor="#007aff" :activeStyle="{
|
||||||
|
color: '#303133',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}" :inactiveStyle="{
|
||||||
|
color: '#606266',
|
||||||
|
transform: 'scale(1)'
|
||||||
|
}" itemStyle="height: 34px; padding-bottom: 10upx;" @change="change">
|
||||||
|
</u-tabs>
|
||||||
|
<view v-if="currentIndex === 0">
|
||||||
|
<view class="inside-content">
|
||||||
|
<text>链接:https://pan.baidu.com/s/1vqFyozWUCc5NSYdqIqcP2A?pwd=uye7</text>
|
||||||
|
<view class="copy-wrap"><text class="copy">复制链接</text></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="imageine" v-else-if="currentIndex === 1">
|
||||||
|
暂无信息
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fix-btn p-20">
|
||||||
|
<u-button shape="circle" type="primary">立即领取</u-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import cmdProgress from "@/components/cmd-progress/cmd-progress.vue"
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
cmdProgress
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabs: [{
|
||||||
|
name: '任务玩法'
|
||||||
|
}, {
|
||||||
|
name: '播放排行'
|
||||||
|
}],
|
||||||
|
currentIndex: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
change(e) {
|
||||||
|
this.currentIndex = e.index
|
||||||
|
},
|
||||||
|
change2(e) {
|
||||||
|
this.promotionActive = e.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.top-img {
|
||||||
|
height: 300upx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
image {
|
||||||
|
height: 600upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fix-btn {
|
||||||
|
width: 100vw;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.information {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 120upx;
|
||||||
|
height: 120upx;
|
||||||
|
border-radius: 10upx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
padding-left: 20upx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #323333;
|
||||||
|
font-size: 28upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 23upx;
|
||||||
|
padding: 2upx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.introduce {
|
||||||
|
padding: 30upx;
|
||||||
|
border-radius: 20upx;
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 25upx;
|
||||||
|
|
||||||
|
>view {
|
||||||
|
padding: 5upx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.way-percent {
|
||||||
|
padding: 30upx 0;
|
||||||
|
border-top: 0;
|
||||||
|
|
||||||
|
.biger {
|
||||||
|
font-size: 30upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #323333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smaller {
|
||||||
|
font-size: 24upx;
|
||||||
|
color: #7d8394;
|
||||||
|
margin-top: 10upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
margin-top: 30upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inside-content {
|
||||||
|
font-size: 28upx;
|
||||||
|
padding: 30upx;
|
||||||
|
color: #666;
|
||||||
|
word-break: break-all;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20upx;
|
||||||
|
margin-top: 20upx;
|
||||||
|
|
||||||
|
.copy-wrap {
|
||||||
|
padding-top: 50upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
color: $uni-theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageine {
|
||||||
|
font-size: 28upx;
|
||||||
|
padding: 30upx;
|
||||||
|
color: #666;
|
||||||
|
word-break: break-all;
|
||||||
|
border-top: 1upx solid #ebedf0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
<template>
|
||||||
|
<c-tabbar :current="3">
|
||||||
|
<view class="container p-20">
|
||||||
|
<view class="banner">
|
||||||
|
<image src="../../static/task/img1.png" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="type-change">
|
||||||
|
<view class="item flex flex-col justify-center items-center" :class="{active: type == 1}"
|
||||||
|
@click="changeType(1)">
|
||||||
|
<text class="t1">任务列表</text>
|
||||||
|
<text class="t2">解锁更多任务模式</text>
|
||||||
|
</view>
|
||||||
|
<view class="item flex flex-col justify-center items-center" :class="{active: type == 2}"
|
||||||
|
@click="changeType(2)">
|
||||||
|
<text class="t1">我的任务</text>
|
||||||
|
<text class="t2">管理和跟踪任务</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
|
||||||
|
<view class="tasks flex flex-col">
|
||||||
|
<view class="task flex flex-row" v-for="item in list" :key="item.id" @click="navigateTo('/pages/task/info/info?id='+item.id)">
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<image class="logo" src="../../static/uni.png" mode="aspectFit"></image>
|
||||||
|
<text class="red">5.00</text>
|
||||||
|
<text class="basis">基础佣金</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col p-r-20" style="width: 0;">
|
||||||
|
<view class="ellipsis">{{item.name}}</view>
|
||||||
|
<view class="flex flex-row">
|
||||||
|
<view class="tag">抖音</view>
|
||||||
|
<view class="tag">CPM</view>
|
||||||
|
</view>
|
||||||
|
<text class="amount">{{(item.totalBonus/100).toFixed(2)}}</text>
|
||||||
|
<text class="amount-txt">总奖金池</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col justify-center items-center">
|
||||||
|
<text class="status">{{stateArr[item.state]}}</text>
|
||||||
|
<view class="c-btn">参与</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="task flex flex-row">
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<image class="logo" src="../../static/uni.png" mode="aspectFit"></image>
|
||||||
|
<text class="red">5.00</text>
|
||||||
|
<text class="basis">基础佣金</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex flex-col p-r-20" style="width: 0;">
|
||||||
|
<view class="ellipsis">【地球行者 香港移民】剪辑发行发哦加废钢</view>
|
||||||
|
<view class="flex flex-row">
|
||||||
|
<view class="tag">抖音</view>
|
||||||
|
<view class="tag">CPM</view>
|
||||||
|
</view>
|
||||||
|
<text class="amount">1,000.00</text>
|
||||||
|
<text class="amount-txt">总奖金池</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col justify-center items-center">
|
||||||
|
<text class="status">已结束</text>
|
||||||
|
<view class="c-btn">参与</view>
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</mescroll-body>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</c-tabbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CTabbar from '@/components/gTabbar.vue'
|
||||||
|
import { getTaskList } from '@/api/index.js'
|
||||||
|
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||||
|
export default {
|
||||||
|
mixins: [MescrollMixin],
|
||||||
|
components: {
|
||||||
|
CTabbar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
type: 1,
|
||||||
|
filter: {},
|
||||||
|
list: [],
|
||||||
|
stateArr: ['未开始', '已开始', '已结束', '已失效', '已完成']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeType(type) {
|
||||||
|
this.type = type
|
||||||
|
},
|
||||||
|
async getList(pageNum) {
|
||||||
|
const res = await getTaskList(pageNum, 10, {
|
||||||
|
...this.filter
|
||||||
|
})
|
||||||
|
if(res.success) {
|
||||||
|
this.mescroll.endBySize(res.data.list.length, parseInt(res.data.total));
|
||||||
|
if (pageNum == 1) this.list = []; //如果是第一页需手动制空列表
|
||||||
|
this.list = this.list.concat(res.data.list);
|
||||||
|
} else {
|
||||||
|
this.mescroll.endErr();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
upCallback(page) {
|
||||||
|
this.getList(page.num)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.banner{
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-change {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-top: 10upx;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 325upx;
|
||||||
|
padding: 30upx;
|
||||||
|
border-radius: 20upx;
|
||||||
|
position: relative;
|
||||||
|
color: #373737;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $uni-theme;
|
||||||
|
.t1 {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.t2 {
|
||||||
|
color: #a5bbf9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-left: 20upx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t1 {
|
||||||
|
font-size: 35upx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t2 {
|
||||||
|
font-size: 25upx;
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks {
|
||||||
|
padding-top: 20upx;
|
||||||
|
}
|
||||||
|
.task {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 30upx;
|
||||||
|
border-radius: 20upx;
|
||||||
|
margin-bottom: 20upx;
|
||||||
|
.logo {
|
||||||
|
width: 120upx;
|
||||||
|
height: 120upx;
|
||||||
|
border-radius: 10upx;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
font-size: 45upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ee2e25;
|
||||||
|
margin-top: 20upx;
|
||||||
|
}
|
||||||
|
.basis {
|
||||||
|
color: #bebebe;
|
||||||
|
font-size: 28upx;
|
||||||
|
padding-top: 3upx;
|
||||||
|
}
|
||||||
|
.status {
|
||||||
|
font-size: 26upx;
|
||||||
|
color: #7e7e7e;
|
||||||
|
}
|
||||||
|
.c-btn {
|
||||||
|
background-color: $uni-theme;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50upx;
|
||||||
|
padding: 10upx 25upx;
|
||||||
|
font-size: 28upx;
|
||||||
|
margin-top: 30upx;
|
||||||
|
}
|
||||||
|
.tag {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #7e7e7e;
|
||||||
|
font-size: 26upx;
|
||||||
|
padding: 8upx 15upx;
|
||||||
|
margin: 20upx 0;
|
||||||
|
margin-right: 20upx;
|
||||||
|
border-radius: 5upx;
|
||||||
|
}
|
||||||
|
.amount {
|
||||||
|
font-size: 45upx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #343434;
|
||||||
|
padding-top: 5upx;
|
||||||
|
}
|
||||||
|
.amount-txt {
|
||||||
|
color: #bebebe;
|
||||||
|
font-size: 28upx;
|
||||||
|
padding-top: 5upx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
After Width: | Height: | Size: 25 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1599859780754" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="77382" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M512 0a512 512 0 1 0 0 1024A512 512 0 0 0 512 0z" fill="#7d7d7b" opacity=".4" p-id="77383" data-spm-anchor-id="a313x.7781069.0.i163" class=""></path><path d="M720.768 565.184l-273.92 158.08c-50.624 29.312-92.096 5.376-92.096-53.12V353.856c0-58.496 41.472-82.432 92.16-53.12l273.92 158.08c50.56 29.248 50.56 77.12 0 106.368z" fill="#ffffff" p-id="77384" data-spm-anchor-id="a313x.7781069.0.i164" class="selected"></path></svg>
|
||||||
|
After Width: | Height: | Size: 803 B |
|
After Width: | Height: | Size: 2.6 KiB |
|
|
@ -0,0 +1,20 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: "customicons"; /* Project id 2878519 */
|
||||||
|
src:url('/static/customicons.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.customicons {
|
||||||
|
font-family: "customicons" !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.youxi:before {
|
||||||
|
content: "\e60e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.wenjian:before {
|
||||||
|
content: "\e60f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.zhuanfa:before {
|
||||||
|
content: "\e610";
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 142 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
|
@ -0,0 +1,283 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title></title>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
border: 0.02667rem solid #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="box"><div class="text"><p style="text-align: center;"><strong>【种草短剧】隐私政策</strong></p>
|
||||||
|
<p style="text-align: right;">版本更新日期:【2023】年【05】月【19】日</p>
|
||||||
|
<p><strong>本政策适用于【种草达人科技(深圳)有限公司】(“</strong><strong>我们”</strong><strong>或“</strong><strong>公司”</strong><strong>)提供的【种草短剧</strong><strong>】及相关服务(“</strong><strong>本产品”</strong><strong>),旨在说明在您使用我们的服务时,我们将如何处理您的个人信息,以及您对这些个人信息享有的权利。</strong></p>
|
||||||
|
<p><strong>请仔细阅读本政策并确定理解我们对您个人信息的处理规则。阅读过程中,如对本政策内容有任何疑问、意见或建议,您可按照本政策尾页中提供的联系方式与我们联系。如您不理解或不同意本政策中的任何条款,您应立即停止使用。一旦您开始使用本产品,即表示您已充分理解并同意本政策。</strong></p>
|
||||||
|
<p><strong>请注意,我们不控制第三方,本政策在任何情况下均不适用于第三方。第三方对您个人信息的收集与使用将遵守第三方的个人信息保护政策。我们建议您在访问第三方时仔细阅读并了解他们的个人信息政策。本政策将帮助您了解以下内容:</strong></p>
|
||||||
|
<p><strong>一、我们如何收集和使用您的个人信息</strong></p>
|
||||||
|
<p><strong>二、我们如何共享、转让、公开披露您的个人信息</strong></p>
|
||||||
|
<p><strong>三、我们如何存储和保护您的个人信息</strong></p>
|
||||||
|
<p><strong>四、您如何管理您的个人信息</strong></p>
|
||||||
|
<p><strong>五、未成年人的个人信息保护</strong></p>
|
||||||
|
<p><strong>六、通知和修订</strong></p>
|
||||||
|
<p><strong>七、如何联系我们</strong></p>
|
||||||
|
<p><strong>一、我们如何收集和使用您的个人信息</strong></p>
|
||||||
|
<p><strong>(一)您需要授权我们收集和使用您个人信息的场景</strong></p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>我们收集的个人信息</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p><strong>使用目的</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p><strong>收集场景</strong></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>帐号注册信息及联系方式</strong></p>
|
||||||
|
<p><strong>包括:微信昵称、微信平台用户ID</strong><strong>、微信平台unionid</strong><strong>、手机号码</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p> </p>
|
||||||
|
<p>用于成为用户、用户登录以及与用户沟通或互动</p>
|
||||||
|
<p> </p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>手机号码及验证信息</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p> </p>
|
||||||
|
<p>用于成为用户及用户登录以及与用户沟通或互动</p>
|
||||||
|
<p> </p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>个人网络信息(IP</strong><strong>地址、Wifi</strong><strong>信息、基站信息等相关信息)</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于与用户提供服务、与用户沟通联系、改善服务质量等目的</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录/使用</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>个人常用设备信息</strong>(包括设备标识符【IMEI、IDFA、Android ID、MAC、OAID 等相关信息】、应用信息【应用崩溃信息、通知开关状态、软件列表等相关信息】、设备参数及系统信息【设备类型、设备型号、操作系统及硬件相关信息】)</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于保障服务安全所必须的功能</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>注册/登录/使用</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong><u>身份信息</u></strong></p>
|
||||||
|
<p><strong><u>包括:姓名、公民身份号码</u></strong></p>
|
||||||
|
</td>
|
||||||
|
<td rowspan="2" width="184">
|
||||||
|
<p> </p>
|
||||||
|
<p>用于分配用户获得合作收益</p>
|
||||||
|
<p> </p>
|
||||||
|
</td>
|
||||||
|
<td rowspan="2" width="184">
|
||||||
|
<p>合作费提现</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong><u>财产信息</u></strong></p>
|
||||||
|
<p><strong><u>包括:银行账户信息、卡号</u></strong></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>第三方账号信息</strong></p>
|
||||||
|
<p>包括用户第三方账号及昵称、用户第三方账号unionid、用户第三方账号openid、手机号、实名信息(含姓名、公民身份号码)、结算账户信息(含银行账户信息、卡号、第三方支付账号信息)</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于第三方平台账号验证绑定、授权,以及查询抖音号用户信息、视频信息、订单数据、橱窗管理、结算合作收益</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>第三方账号管理及结算合作收益</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="185">
|
||||||
|
<p><strong>反馈信息</strong></p>
|
||||||
|
<p><strong>包括:</strong>您通过本政策公示联系方式提交给我们的信息。</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>用于用户与我们联系,提升用户体验</p>
|
||||||
|
</td>
|
||||||
|
<td width="184">
|
||||||
|
<p>联系我们</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> </p>
|
||||||
|
<p>(二)您可以选择授权提供个人信息的场景</p>
|
||||||
|
<p>您可以通过访问您所依托的移动应用程序(微信或种草短剧 APP)的隐私设置逐项查看您上系统权限的开启状态,并可以决定设置权限的开启或关闭(如适用)。请您注意,您开启这些权限后且在种草短剧内授权即代表您授权我们可以收集和使用这些个人信息来实现对应的功能,您关闭权限即代表您取消了授权,则我们将不再继续收集和使用您的相关个人信息,也无法为您提供上述与这些授权所对应的功能。您关闭权限的决定不会影响此前基于您的授权所进行的个人信息的处理。</p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td width="189">
|
||||||
|
<p><strong>收集的权限</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p><strong>权限与获取信息描述</strong></p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p><strong>目的/</strong><strong>用途</strong></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="189">
|
||||||
|
<p>相册权限</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>允许使用相册</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>用于保存或上传图片</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="189">
|
||||||
|
<p>定位权限</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>允许使用定位</p>
|
||||||
|
</td>
|
||||||
|
<td width="189">
|
||||||
|
<p>用于分析用户地域标签分配业务</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong>(三)征得同意的例外</strong></p>
|
||||||
|
<p>您应充分知晓,以下情形中,我们收集、使用个人信息无需征得您的授权同意:</p>
|
||||||
|
<p>1.与国家安全、国防安全有关的;</p>
|
||||||
|
<p>2.为订立、履行个人作为一方当事人的合同所必需;</p>
|
||||||
|
<p>3.为履行法定职责或者法定义务所必需;</p>
|
||||||
|
<p>4.为应对突发公共卫生事件,或者紧急情况下为保护自然人的生命健康和财产安全所必需;</p>
|
||||||
|
<p>5.为公共利益实施新闻报道、舆论监督等行为,在合理的范围内处理个人信息;</p>
|
||||||
|
<p>6.依照本法规定在合理的范围内处理个人自行公开或者其他已经合法公开的个人信息;</p>
|
||||||
|
<p>7.用于维护所提供的服务的安全稳定运行所必需的,例如发现、处置产品与/或服务的故障;</p>
|
||||||
|
<p>8.收集将个人信息匿名化处理后形成的数据;</p>
|
||||||
|
<p>9.我们因重组、分拆、调整等主体变更导致向继受者提供或者转移个人信息的情形;</p>
|
||||||
|
<p>10.法律、行政法规规定的其他情形。</p>
|
||||||
|
<p><strong>(四)个人信息使用规则</strong></p>
|
||||||
|
<p>1.我们会根据本《隐私权政策》所述,为实现我们的产品与/或服务功能而对所收集的个人信息进行使用。</p>
|
||||||
|
<p>2.请您了解并同意,对于您在使用我们的产品与/或服务时所提供的所有个人信息,除非您删除或通过系统设置拒绝我们收集,否则将被视为在您使用我们的产品与/或服务期间持续授权同意我们使用。</p>
|
||||||
|
<p>3.当我们要将您的个人信息用于本隐私声明未载明的其它用途时,或基于特定目的收集而来的个人信息用于其他目的时,会事先征求您的明示同意。请您理解,我们向您提供的产品与/或服务将不断更新变化。如果您选择使用本隐私声明中尚未列明的其他产品与/或服务时,我们会在收集您的个人信息前通过协议、页面提示等方式向您详细说明信息收集的目的、方式、范围并征求您的同意。若您不同意提供前述信息,您将无法使用该项产品与/或服务,但不影响您使用现有产品与/或服务。</p>
|
||||||
|
<p><strong>二、我们如何共享、转让、公开披露您的个人信息</strong></p>
|
||||||
|
<p><strong>(一)共享</strong></p>
|
||||||
|
<p>我们不会与非服务提供者以外的公司、组织和个人共享您的个人信息,但以下情况除外:</p>
|
||||||
|
<p>1.在获取明确同意情况下共享:获得您的明确同意后,我们会与其他方共享您的个人信息。例如,如果我们委托第三方向您提供产品或服务时,我们会在征得您同意后将上述信息共享给第三方,如果您拒绝提供此类信息,我们将无法完成相关交付服务。</p>
|
||||||
|
<p>2.在法定情形下共享:我们会根据法律法规规定、诉讼争议解决需要,或按行政、司法机关依法提出的要求,对外共享您的个人信息。</p>
|
||||||
|
<p>3.我们可能会委托授权合作伙伴为您提供某些服务或代表我们履行职能,在此之前我们会和他们通过不限于签订协议的方式约定双方的权利和义务。我们仅会出于合法、正当、必要、特定、明确的目的处理您的信息,授权合作伙伴只能接触到为其履行职责所需信息,且不能将此信息用于任何其他目的。</p>
|
||||||
|
<p>4.为处理您与他人的纠纷或争议。</p>
|
||||||
|
<p><strong>(二)转让</strong></p>
|
||||||
|
<p>我们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:</p>
|
||||||
|
<p>1.事先获得您明确的同意或授权;</p>
|
||||||
|
<p>2.根据适用的法律法规、法律程序的要求、强制性的行政或司法要求所必须的情况进行提供;</p>
|
||||||
|
<p>3.符合与您签署的相关协议(包括在线签署的电子协议以及相应的平台规则)或其他的法律文件约定所提供;</p>
|
||||||
|
<p>4.随着我们业务的发展,我们及我们的关联方有可能进行合并、收购、资产转让或类似的交易,<strong>如涉及个人信息的转让,我们会要求受让您个人信息的公司、组织继续接受本隐私声明的约束,否则</strong><strong>,</strong><strong>我们将要求该公司、组织重新征求您的授权同意。</strong></p>
|
||||||
|
<p><strong>(三)公开披露</strong></p>
|
||||||
|
<p>我们仅会在以下情况,公开披露您的个人信息:</p>
|
||||||
|
<p>1.获得您明确同意或基于您的主动选择,我们会公开披露您的个人信息;</p>
|
||||||
|
<p>2.根据法律、法规的要求、强制性的行政执法或司法要求所必须提供您个人信息的情况下,我们会依据所要求的个人信息类型和披露方式公开披露您的个人信息。在符合法律法规的前提下,当我们收到上述披露信息的请求时,我们会要求必须出具与之相应的法律文件。</p>
|
||||||
|
<p>3.对违规账号、欺诈行为进行处罚公告时,我们会披露相关账号的必要信息。</p>
|
||||||
|
<p><strong>(四)共享、转让、公开披露个人信息时事先征得授权同意的例外</strong></p>
|
||||||
|
<p>以下情形中,共享、转让、公开披露您的个人信息无需事先征得您的授权同意:</p>
|
||||||
|
<p>1.与我们履行法律法规规定的义务相关的;</p>
|
||||||
|
<p>2.根据法律法规的规定或行政、司法机构、国家部门等有权机关的要求依法提供的;</p>
|
||||||
|
<p>3.出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;</p>
|
||||||
|
<p>4.您自行向社会公众公开的个人信息;</p>
|
||||||
|
<p>5.与国家安全、国防安全直接相关的;</p>
|
||||||
|
<p>6.从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道。</p>
|
||||||
|
<p>根据法律规定,共享、转让经去标识化处理的个人信息,且确保数据接收方无法复原并重新识别个人信息主体的,不属于个人信息的对外共享、转让及公开披露行为,对此类数据的共享、转让、公开披露、保存及处理将无需另行向您通知并征得您的同意。</p>
|
||||||
|
<p><strong>三、我们如何存储和保护您的个人信息</strong></p>
|
||||||
|
<p><strong>(一)存储您的个人信息</strong></p>
|
||||||
|
<p>1.存储地域范围</p>
|
||||||
|
<p>我们在中华人民共和国境内收集和产生的个人信息将存储在中华人民共和国境内,但以下情形除外:(1)法律法规有明确规定的;(2)依法征得您的同意。在上述除外情形中,我们会要求数据接收方按照本政策以及其他相关的安全保密措施来处理个人信息。</p>
|
||||||
|
<p>2.存储期限</p>
|
||||||
|
<p>除法律法规规定、获得您的同意或双方另有约定外,我们通常仅在实现本政策所述目的所必需的期限内保留您的个人信息。</p>
|
||||||
|
<p>3.终止服务</p>
|
||||||
|
<p>如果我们终止服务或运营,我们会至少提前三十日向您通知,并在终止服务或运营后对您的个人信息进行删除。</p>
|
||||||
|
<p><strong>(二)保护您个人信息的措施</strong></p>
|
||||||
|
<p>1.我们非常重视个人信息安全,并采取符合行业标准的安全技术措施保护您提供的个人信息的安全。</p>
|
||||||
|
<p>2.我们通过建立专门的管理制度、流程、组织等管理措施以保障信息的安全。例如,我们使用用户信息集中管理系统,我们只允许有必要接触用户信息的工作人员访问该系统查询和管理客户信息。我们严格设定访问用户信息的权限分级,同时要求可能接触到您个人信息的所有人员履行相应的保密义务。我们还不时对工作人员培训相关法律法规及隐私安全准则,强化宣导安全意识。</p>
|
||||||
|
<p>3.若发生个人信息泄露等安全事件,我们会启动应急预案,阻止安全事件扩大。我们会及时将事件的基本情况、处置措施、降低风险建议等以电话、推送通知等方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。</p>
|
||||||
|
<p><strong>四、您如何管理个人信息</strong></p>
|
||||||
|
<p><strong>(一)查询、更正和补充您的个人信息</strong></p>
|
||||||
|
<p>您有权查询、更正或补充您的信息。若您无法查看或更正的信息,请通过本政策公示的联系方式协助您查询、更正或补充。</p>
|
||||||
|
<p><strong>(二)删除您的个人信息</strong></p>
|
||||||
|
<p>在以下情形中,您可以向我们提出删除个人信息的请求:</p>
|
||||||
|
<p>1.如果我们处理个人信息的行为违反法律法规;</p>
|
||||||
|
<p>2.如果我们收集、使用您的个人信息,却未征得您的明确同意;</p>
|
||||||
|
<p>3.如果我们处理个人信息的行为严重违反了与您的约定;</p>
|
||||||
|
<p>4.如果您不再使用我们的产品或服务;</p>
|
||||||
|
<p>5.如果我们停止为您提供产品或服务。</p>
|
||||||
|
<p>当您或我们协助您删除相关信息后,因为适用的法律和安全技术,我们可能无法立即从备份系统中删除相应的信息,我们将安全地存储您的个人信息并将其与任何进一步处理隔离,直到备份可以清除或实现匿名。</p>
|
||||||
|
<p><strong>(三)改变您授权同意的范围或撤回您的授权</strong></p>
|
||||||
|
<p>请您理解,每个业务功能需要一些基本的个人信息才能得以完成,当您撤回同意或授权后,我们无法继续为您提供撤回同意或授权所对应的服务,也不再处理您相应的个人信息。但您撤回同意或授权的决定,不会影响此前基于您的授权而开展的个人信息处理。</p>
|
||||||
|
<p><strong>(四)注销帐号</strong></p>
|
||||||
|
<p><strong>您可以通过本政策“</strong><strong>如何联系我们”</strong><strong>部分提供的联系方式注销您的账号。请注意,在您注销账号后,我们将根据法律规定删除或匿名化处理您的个人信息,请谨慎进行账号注销操作。</strong></p>
|
||||||
|
<p><strong>(五)响应您的请求</strong></p>
|
||||||
|
<p>为保障安全,您可能需要提供书面请求,或以其他方式证明您的身份。我们将会先要求您验证自己的身份,然后再处理您的请求。我们将在【15】天内做出答复。</p>
|
||||||
|
<p>对于您合理的请求,我们原则上不收取费用,但对多次重复、超出合理限度的请求,我们将酌情收取一定费用。对于与您的身份不直接关联的信息、无端重复信息,或者需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者不切实际的请求,我们可能会予以拒绝。</p>
|
||||||
|
<p>在以下情形中,按照法律法规要求,我们将无法响应您的请求:</p>
|
||||||
|
<p>1.与我们履行法律法规规定的义务相关的;</p>
|
||||||
|
<p>2.与国家安全、国防安全有关的;</p>
|
||||||
|
<p>3.与公共安全、公共卫生、重大公共利益有关的;</p>
|
||||||
|
<p>4.与犯罪侦查、起诉、审判和执行判决等有关的;</p>
|
||||||
|
<p>5.有充分证据表明个人信息主体存在主观恶意或滥用权利的;</p>
|
||||||
|
<p>6.响应您的请求将导致您或其他个人、组织的合法权益受到严重损害的;</p>
|
||||||
|
<p>7.涉及商业秘密的。</p>
|
||||||
|
<p><strong>五、未成年人的个人信息保护</strong></p>
|
||||||
|
<p>(一)本政策所指的未成年人是指不满18周岁的个人,如果没有父母或监护人的同意,未成年人不得创建自己的用户帐户。如您为未成年人的,建议您请您的父母或监护人仔细阅读本隐私权政策,并在征得您的父母或监护人同意的前提下使用我们的服务或向我们提供信息。</p>
|
||||||
|
<p>(二)对于经父母或监护人同意使用我们的产品或服务而收集未成年人个人信息的情况,我们只会在法律法规允许、父母或监护人明确同意或者保护未成年人所必要的情况下使用、共享、转让或披露此信息。</p>
|
||||||
|
<p>(三)如果我们发现自己在未事先获得可证实的父母同意的情况下收集了未成年人的个人信息,则会设法尽快删除相关数据。</p>
|
||||||
|
<p><strong>六、通知和修订</strong></p>
|
||||||
|
<p>(一)为给您提供更好的服务以及随着种草短剧业务的发展,我们的隐私权政策可能变更。但未经您明确同意,我们不会限制您按照本隐私权政策所应享有的权利。我们会在生效前通过公告或以其他适当方式提醒您对隐私权政策所做的任何变更。如您继续使用我们的服务,表示同意接受修订后的本隐私政策的内容。</p>
|
||||||
|
<p>(二)本政策所指的重大变更包括但不限于:</p>
|
||||||
|
<p>1.我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式等;</p>
|
||||||
|
<p>2.我们在组织架构等方面发生重大变化。如并购重组等引起的信息控制者变更等;</p>
|
||||||
|
<p>3.个人信息共享、转让或公开披露的主要对象发生变化;</p>
|
||||||
|
<p>4.您参与个人信息处理方面的权利及其行使方式发生重大变化;</p>
|
||||||
|
<p>5.我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化;</p>
|
||||||
|
<p>6.个人信息安全影响评估报告表明存在高风险。</p>
|
||||||
|
<p>(三)您可以通过“【<strong>我的</strong><strong>-</strong><strong>隐私权政策</strong>】”中查看本政策的最新版本。</p>
|
||||||
|
<p><strong>七、如何联系我们</strong></p>
|
||||||
|
<p>(一)本政策提及的可能需要与我们取得联系的情况下,或您对本政策内容有任何疑问、意见或建议的,您可以通过以下方式联系我们:</p>
|
||||||
|
<p>①小程序页面扫码添加客服企业微信</p>
|
||||||
|
<p>②电子邮件:【13951762324@163.com】</p>
|
||||||
|
<p>③联系地址:【深圳湾科技生态园9栋A1座3102室】</p>
|
||||||
|
<p>(二) 一般情况下,我们将在收到您反馈并验证您的身份后【十五】天内回复。如果您对我们的回复不满意,特别是您认为我们的个人信息处理行为损害了您的合法权益,您可以向网信、电信、公安及工商等监管部门进行投诉或举报,亦或向被告住所地有管辖权的法院提起诉讼来寻求解决方案。</p></div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 587 B |
|
After Width: | Height: | Size: 600 B |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
|
@ -0,0 +1,132 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="box" data-v-c44c8a1a=""><div class="text" data-v-c44c8a1a=""><p style="text-align: center;"><strong>【种草短剧</strong><strong>】用户服务协议</strong></p>
|
||||||
|
<p style="text-align: right;">发布日期:2023年 05月 19日</p>
|
||||||
|
<p>欢迎您来到并使用种草短剧平台服务!</p>
|
||||||
|
<p> </p>
|
||||||
|
<p>本协议由用户(以下或称“您”)与种草短剧平台经营者(以下或称“种草短剧”,详见定义条款)共同签订,种草短剧平台经营者依据本协议为您提供服务。</p>
|
||||||
|
<p><strong>请您在访问或使用前,仔细阅读本协议中所有内容,尤其是种草短剧</strong><strong>免责条款、对您的权利限制条款以及争议解决条款等重要条款内容,本协议中会以加粗显示方式提示您注意,您应重点阅读。</strong>如您对协议有任何疑问,可向种草短剧平台客服咨询。</p>
|
||||||
|
<p>您有权选择同意或不同意本协议。当您按照注册页面提示填写信息、阅读并同意本协议且完成全部注册程序后,或使用第三方账号登录种草短剧平台,即视为您已充分阅读、理解并接受本协议的全部内容,并与种草短剧达成一致,成为种草短剧平台“用户”。阅读本协议的过程中,如果您不同意本协议或其中任何条款约定,您应立即停止注册程序并停止使用种草短剧平台服务。</p>
|
||||||
|
<p><strong><em><u>请您在决定登录、注册或使用种草短剧</u></em></strong><strong><em><u>平台服务前再次确认您已知悉并完全理解本协议的所有内容。如果您未满16</u></em></strong><strong><em><u>周岁,或已满16</u></em></strong><strong><em><u>周岁未满18</u></em></strong><strong><em><u>周岁且不能以自己的劳动收入作为主要收入来源的,请在法定监护人的陪同下阅读本协议,请务必在家长和其他法定监护人的陪同下阅读本协议,并在进行注册、使用种草短剧</u></em></strong><strong><em><u>平台的其他任何服务前,应事先征得您的家长和其他法定监护人的同意。</u></em></strong></p>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong>1</strong><strong>、 </strong><strong>定义</strong></p>
|
||||||
|
<p>1.1种草短剧平台的经营者/种草短剧:指实际经营种草短剧平台的法律主体,现为杭州亮宇网络科技有限公司。<strong><u>本协议项下,麻雀</u></strong><strong><u>MATRIX</u></strong><strong><u>平台经营者可能根据种草短剧</u></strong><strong><u>平台的业务调整而发生变更,具体以种草短剧</u></strong><strong><u>平台公示的信息为准。种草短剧</u></strong><strong><u>平台经营者的变更不会影响本协议项下约定的各项权利义务。您有权选择同意或不同意本协议项下种草短剧</u></strong><strong><u>主体的变更,具体适用本协议第2.2</u></strong><strong><u>条关于协议变更的约定。</u></strong></p>
|
||||||
|
<p>1.2 种草短剧平台服务:指种草短剧基于互联网,以微信小程序、app等形态(包括未来技术发展出现的新的服务形态)向您提供的各项服务,关于“种草短剧”及其服务的解释权归种草短剧所有。</p>
|
||||||
|
<p>1.3 种草短剧平台规则:包括所有种草短剧已经发布及后续可能发布、修订的各类规则、规范、解读、实施细则、通知、公告等。</p>
|
||||||
|
<p> </p>
|
||||||
|
<p><strong>2</strong><strong>、 </strong><strong>协议范围及变更</strong></p>
|
||||||
|
<p>2.1协议范围:由于互联网高速发展,您与种草短剧签署的本协议列明的条款并不能完整罗列并覆盖您与种草短剧所有权利与义务,现有的约定也不能保证完全符合未来发展的需求。同时,种草短剧平台隐私权政策、种草短剧平台规则均为本协议的补充协议,与本协议不可分割且具有同等法律效力。如您使用种草短剧平台服务,视为您同意上述补充协议。</p>
|
||||||
|
<p><em><u>2.2 </u></em><strong><em><u>协议变更:种草短剧</u></em></strong><strong><em><u>可根据国家法律法规变化及维护交易秩序需要,种草短剧</u></em></strong><strong><em><u>有权根据“种草短剧</u></em></strong><strong><em><u>”及其服务的调整对本协议内容进行修改、更新、废止,变更后的协议将在相关页面或其他合适的方式公布。用户如果不同意变更后的协议,应放弃使用“种草短剧</u></em></strong><strong><em><u>”或相关服务;如果用户选择在协议变更后继续访问或使用“种草短剧</u></em></strong><strong><em><u>”,则视为用户接受已生效的变更事项。</u></em></strong></p>
|
||||||
|
<p><strong>3</strong><strong>、 </strong><strong>用户账户登录与使用</strong></p>
|
||||||
|
<p><strong>3.1 </strong><strong>账户登录</strong></p>
|
||||||
|
<p><strong>用户资格</strong>:您确认,在您开始注册/登录程序使用种草短剧平台服务前,您应当具备中华人民共和国法律规定的与您行为相适应的民事行为能力。若您不具备前述与您行为相适应的民事行为能力,则您及您的监护人应依照法律规定承担因此而导致的一切后果。</p>
|
||||||
|
<p><strong>信息真实:</strong>在使用种草短剧平台服务时,您应当按种草短剧平台页面的提示准确完整地提供您的信息。如果您提供的信息不合法、不真实、不准确、不详尽的,您需承担因此引起的相应责任及后果,并且种草短剧保留终止您使用种草短剧各项服务的权利。您了解并同意,您有义务保持您提供信息的真实性及有效性。</p>
|
||||||
|
<p><strong>真实身份:</strong>因国家法律法规、监管要求,您有可能需要在使用该等服务的特定环节中填写真实的个人信息,并需通过相关验证流程后方可使用服务,如您填写的信息不完整、不真实或未通过验证,将导致您无法使用该服务、损害自身、他人利益或造成其他不利后果,该等后果将由您自行承担。</p>
|
||||||
|
<p><strong>更新维护:</strong>您应当及时更新您提供的信息,在法律有明确规定要求种草短剧作为平台服务提供者必须对部分用户的信息进行核实的情况下,种草短剧将依法不时地对您的信息进行检查核实,您应当配合提供最新、真实、完整、有效的信息。</p>
|
||||||
|
<p>如种草短剧按您最后一次提供的信息与您联系未果、您未按种草短剧的要求及时提供信息、您提供的信息存在明显不实或行政司法机关核实您提供的信息无效的,您将承担因此对您自身、他人及种草短剧造成的全部损失与不利后果。种草短剧可向您发出询问或要求整改的通知,并要求您进行重新认证,直至中止、终止对您提供部分或全部种草短剧平台服务,种草短剧对此不承担责任。</p>
|
||||||
|
<p><strong>用户名的合法性:</strong>您设置的种草短剧平台用户名(昵称)不得违反国家法律法规及种草短剧平台规则关于用户名(昵称)的管理规定,不得包含违法、涉嫌侵犯他人权利、有违公序良俗或干扰种草短剧平台运营秩序等相关信息,否则种草短剧有权向您发出要求修改的通知,直至中止、终止对您提供部分或全部种草短剧平台服务,种草短剧对此不承担责任。</p>
|
||||||
|
<p><strong>3.2 </strong><strong>账户说明</strong></p>
|
||||||
|
<p><strong>账户获得:</strong>当您按照登录页面提示填写信息、阅读并同意本协议且完成全部登录程序后,您可成为种草短剧平台用户。</p>
|
||||||
|
<p><strong><em><u>账户登录与使用:</u></em></strong><strong><em><u>您有权使用您确认的手机号码或第三方账号登录种草短剧</u></em></strong><strong><em><u>平台。由于您的种草短剧</u></em></strong><strong><em><u>平台账户关联您的个人信息及种草短剧</u></em></strong><strong><em><u>平台商业信息,您的种草短剧</u></em></strong><strong><em><u>平台账户仅限您本人使用。未经种草短剧</u></em></strong><strong><em><u>同意,您直接或间接授权第三方使用您种草短剧</u></em></strong><strong><em><u>平台账户或获取您账户项下信息的行为无效。如根据种草短剧</u></em></strong><strong><em><u>平台规则中约定的违约认定程序及标准判断您账户的使用可能危及您的账户安全及/</u></em></strong><strong><em><u>或种草短剧</u></em></strong><strong><em><u>平台信息安全的,种草短剧</u></em></strong><strong><em><u>平台可拒绝提供相应服务或终止本协议、冻结或注销账户,并可要求您承担因此产生的一切责任和损失。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>限制冻结:</u></em></strong><strong><em><u>您知悉并同意,在符合法律法规的规定,或经国家机关要求的前提下,种草短剧</u></em></strong><strong><em><u>平台有权对您的注册账户进行限制或冻结,在该等情况下,您可能无法继续登陆或使用您的账户。</u></em></strong></p>
|
||||||
|
<p><strong>3.3 </strong><strong>账户安全规范</strong></p>
|
||||||
|
<p>账户安全保管义务:您的账户为您自行设置并由您保管。凡经您的账号和密码成功登录使用种草短剧平台,即视为您的使用行为。因此,建议您务必保管好您的账户,并确保您在每个上网时段结束时退出登录并以正确步骤离开种草短剧平台。您知悉并同意,如您在账户信息的保管上、相关上网设备的网络安全维护上存在任何过失,或是因您主动泄露或因您遭受他人攻击、诈骗等行为导致账户丢失、泄露,您应对此产生的任何损失和后果负责,种草短剧对此不负任何责任,您应通过司法、行政等救济途径向侵权行为人追偿,如种草短剧因此产生相关支出,种草短剧将有权向您追偿。</p>
|
||||||
|
<p><strong><em><u>账户行为责任自负:除种草短剧</u></em></strong><strong><em><u>存在过错外,您应对您账户项下的所有行为结果(包括但不限于在线签署各类协议、履行义务、披露信息等)负责,通过您的账户所发生的上述各项行为将视为您本人的真实意思表示。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>您通过账户在接受种草短剧</u></em></strong><strong><em><u>平台的各项服务中所上传、发送的任何内容都应具有合法来源,如相关内容涉及任何第三方的合法权益,应事先获得相应的许可。如种草短剧</u></em></strong><strong><em><u>平台收到涉及您的相关举报或投诉,种草短剧</u></em></strong><strong><em><u>平台可采取相关法律法规所要求或允许的方式,向相关争议方、相关部门提供包括账户在内的必要的信息,以便解决纠纷争议,保护正当权利人的合法权益。</u></em></strong></p>
|
||||||
|
<p>日常维护须知:如发现任何未经授权使用您账户登录种草短剧平台或其他可能导致您账户遭窃、遗失的情况,建议您立即通知种草短剧。您理解种草短剧对您的任何请求采取行动均需要合理时间,且种草短剧应您请求而采取的行动可能无法避免或阻止侵害后果的形成或扩大,除种草短剧存在法定过错外,种草短剧不承担责任。</p>
|
||||||
|
<p>4、 种草短剧平台服务及规范</p>
|
||||||
|
<p><strong>4.1 </strong><strong>任务详情:</strong>当您选择变现项目时,您可以在“首页”中查看各变现项目的详情。</p>
|
||||||
|
<p><strong>4.2 </strong><strong>数据:</strong>当您选择、完成变现项目任务时,您可以在“数据”中查看您的数据统计及预估收益,预估收益仅供参考,具体以您实际收到的为准。</p>
|
||||||
|
<p>4.3<strong>费用结算:</strong>若您通过种草短剧领取变现项目任务并按照要求履行完毕,种草短剧或种草短剧委托的第三方将向您支付相应费用,种草短剧亦有权通过各变现项目对应的推广平台分佣结算功能实现线上分佣。结算过程中,若需您提供必要协助(包括但不限于推广平台线上分佣所需的资料提交等),您应无条件配合,否则种草短剧有权不予结算且无需承担任何违约责任。</p>
|
||||||
|
<p><strong><em><u>提现规则:部分合作费您可在种草短剧</u></em></strong><strong><em><u>平台申请提现,具体提现规则(包括但不限于提现限额、次数、提现日期、支付周期等)以提现页面规定(包括但不限于协议、提现功能设置)为准。平台可根据业务发展需要、提现策略变更等因素调整提现规则,您对此表示理解且接受。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>若您作为种草短剧</u></em></strong><strong><em><u>合作方(代理</u></em></strong><strong><em><u>)引进的创作者,种草短剧</u></em></strong><strong><em><u>已根据其与合作方的合作协议,自行或通过指定的第三方与合作方完成费用结算的,则无需向您支付任何费用。您与合作方之间有关费用结算产生的任何争议,均与种草短剧</u></em></strong><strong><em><u>无涉。</u></em></strong></p>
|
||||||
|
<p><strong>4.4</strong><strong>税费约定:</strong>您通过种草短剧产生的所有收益,均应自行承担税费并依法履行缴税义务。</p>
|
||||||
|
<p><strong><em><u>4.5 </u></em></strong><strong><em><u>责任限制</u></em></strong></p>
|
||||||
|
<p><strong><em><u>4.5.1 </u></em></strong><strong><em><u>不可抗力:不可抗力是指不能预见、不能克服并不能避免的客观事件,包括地震、台风、水灾、火灾、战争、国际或国内运输中断、流行病、罢工,以及根据中国法律或一般商业惯例认作不可抗力的其他事件。如果发生不可抗力事件,影响一方履行其在本合同项下的义务,则在不可抗力造成的延误期内导致的合同履行障碍、履行瑕疵、履行延后等情形,而不视为违约。宣称发生不可抗力的一方应迅速书面通知其他对方,并在其后的15</u></em></strong><strong><em><u>天内提供证明不可抗力发生及其持续时间的足够证据。如果发生不可抗力事件,双方应立即互相协商,以找到公平的解决办法,并且应尽一切合理努力将不可抗力的影响减少到最低限度。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>4.5.2 </u></em></strong><strong><em><u>第三方原因:种草短剧</u></em></strong><strong><em><u>依照法律规定履行基础保障义务的前提下,因电力供应故障、通讯网络故障等公共服务因素或黑客攻击、计算机病毒侵入或发作等第三方因素导致种草短剧</u></em></strong><strong><em><u>无法提供相关服务或提供服务有瑕疵或迟延的,种草短剧</u></em></strong><strong><em><u>公司应及时向您进行通知、采取紧急措施避免扩大损失。如种草短剧</u></em></strong><strong><em><u>未尽通知义务或处理存在过错导致扩大化损失的,应就该部分损失承担责任。 </u></em></strong></p>
|
||||||
|
<p><strong><em><u>4.5.3 </u></em></strong><strong><em><u>非担保:除非另有明确书面说明,在符合法律法规规定的情况下,种草短剧</u></em></strong><strong><em><u>不对种草短剧</u></em></strong><strong><em><u>平台上的信息、内容、材料、产品或服务做任何形式的明示或默示的声明或担保。</u></em></strong></p>
|
||||||
|
<p><strong>5</strong><strong>、 </strong><strong>用户信息的保护及授权</strong></p>
|
||||||
|
<p>5.1 【授权收集】在您使用种草短剧提供的服务时,您同意种草短剧收集、存储、使用、披露和保护您的个人信息(即能够独立或与其他信息结合后识别用户身份的信息,包括但不限于姓名、手机号、收款银行账号、公民身份号码等)。</p>
|
||||||
|
<p><strong><em><u>5.2 </u></em></strong><strong><em><u>【信息保护】尊重和保护用户的个人信息是种草短剧</u></em></strong><strong><em><u>的一项基本政策。种草短剧</u></em></strong><strong><em><u>将按照本协议及《隐私权政策》的规定收集、使用、储存、保护和提供您的个人信息。本协议对个人信息保护相关内容未作明确规定的,请参见《隐私权政策》。</u></em></strong></p>
|
||||||
|
<p><strong>6</strong><strong>、 </strong><strong>用户行为规范</strong></p>
|
||||||
|
<p>6.1 您知悉并承诺,在使用种草短剧所提供的服务的过程中,您应遵守相关法律法规,不应从事或协助、教唆他人从事违反法律法规的规定、影响正常服务提供或损害他人合法利益的行为,包括但不限于:</p>
|
||||||
|
<p>(1)利用种草短剧平台或相关服务从事违反国家法律法规禁止性规定的行为;</p>
|
||||||
|
<p>(2)因对种草短剧平台相关服务的使用行为导致种草短剧卷入政治和公共事件;</p>
|
||||||
|
<p>(3)入侵种草短剧平台计算机信息系统,或从事危害计算机信息网络安全的活动;</p>
|
||||||
|
<p>(4)擅自复制和使用网络上未公开和未授权的文件。除相关著作权人明示同意,不应在网络中擅自破解、传播、下载或复制第三人享有著作权的软件或进行其他任何侵害他人知识产权的活动;</p>
|
||||||
|
<p>(5)盗取他人种草短剧账户、银行账号等信息或盗取他人种草短剧账户中的资产中的资产;</p>
|
||||||
|
<p>(6)其他干扰种草短剧平台正常运转或正常交易秩序、违反公平或诚实信用原则的行为;</p>
|
||||||
|
<p>(7)使用欺骗手段及(或)利用系统bug、漏洞等虚构履约状态谋取利益。</p>
|
||||||
|
<p>6.2 【信息发布】用户使用种草短剧的服务时必须遵守有关法律法规,不得在种草短剧上或者利用种草短剧的服务制作、复制、发布、传播以下信息:</p>
|
||||||
|
<p>(1)违反国家法律法规禁止性规定的;</p>
|
||||||
|
<p>(2)政治宣传、封建迷信、淫秽、色情、赌博、暴力、恐怖或者教唆犯罪的;</p>
|
||||||
|
<p>(3)欺诈、虚假、不准确或存在误导性的;</p>
|
||||||
|
<p>(4)侵犯他人知识产权或涉及第三方商业秘密及其他专有权利的;</p>
|
||||||
|
<p>(5)侮辱、诽谤、恐吓、涉及他人隐私等侵害他人合法权益的;</p>
|
||||||
|
<p>(6)存在可能破坏、篡改、删除、影响种草短剧平台任何系统正常运行或未经授权秘密获取种草短剧平台及其他用户的数据、个人资料的病毒、木马、爬虫等恶意软件、程序代码的;</p>
|
||||||
|
<p>(7)其他违背社会公共利益或公共道德或依据相关种草短剧平台协议、规则的规定不适合在种草短剧平台上发布的。</p>
|
||||||
|
<p><strong>6.3 </strong><strong>软件使用及规范</strong></p>
|
||||||
|
<p>【软件使用】如果您从未经种草短剧授权的第三方获取软件或与该软件名称相同的安装程序,种草短剧无法保证该软件能够正常使用,由此造成的相关损失,种草短剧不予负责。</p>
|
||||||
|
<p>基于改善用户体验、修复漏洞、保障安全性等因素考虑,种草短剧将不时对软件进行更新,请您及时核对并更新最新版本。</p>
|
||||||
|
<p>除非法律允许或种草短剧书面许可,您使用种草短剧平台过程中不得从事下列任一行为:</p>
|
||||||
|
<p>(1)删除、编辑或遮挡软件及其副本上关于著作权、商标或其他权利标识或标记的信息;</p>
|
||||||
|
<p>(2)对软件进行反向工程、反向汇编、反向编译,或者以其他方式挖掘、提取软件的源代码;</p>
|
||||||
|
<p>(3)对种草短剧拥有知识产权的内容进行使用、出租、出借、出售、复制、修改、链接、转载、汇编、发表、出版、建立镜像站点等;</p>
|
||||||
|
<p>(4)对软件或者软件运行过程中释放到任何终端内存中的数据、软件运行过程中客户端与服务器端的交互数据,以及软件运行所必需的系统数据,进行复制、修改、增加、删除、挂接运行或创作任何衍生作品,形式包括但不限于使用插件、外挂或非经种草短剧授权的第三方工具/服务接入软件和相关系统;</p>
|
||||||
|
<p>(5)通过修改或伪造软件运行中的指令、数据,增加、删减、变动软件的功能或运行效果,或者将用于上述用途的软件、方法进行运营或向公众传播,无论这些行为是否为商业目的;</p>
|
||||||
|
<p>(6)通过非种草短剧开发、授权的第三方软件、插件、外挂、系统,登录或使用种草短剧平台及服务,或制作、发布、传播上述工具;</p>
|
||||||
|
<p>(7)自行或者授权他人、第三方软件对本软件及其组件、模块、数据进行干扰。</p>
|
||||||
|
<p><strong>7</strong><strong>、 </strong><strong>所有权及知识产权</strong></p>
|
||||||
|
<p>7.1 种草短剧软件及相关服务中提供的任何内容(包括但不限于软件、技术、程序、网页、文字、图片、图像、音频、视频、图表、版面设计、电子文档等)的知识产权属于种草短剧或(及)关联公司所有。本公司提供本服务时所依托的软件的著作权、专利权及其他知识产权均归公司所有。未经本公司事先书面许可,您承诺不应且不应允许或协助任何人以任何形式(包括但不限于通过任何机器人、蜘蛛等程序或设备)监视、复制、传播、展示、镜像、上载、下载“种草短剧”软件及相关服务中的内容或创造相关衍生作品。未经本公司事先书面同意,您不得擅自使用、掩盖或更改本公司的版权声明、商标或其他权利声明(若有),不得将本公司的商标以任何方式展示使用或作其他处理,也不得实施向他人明示或暗示有权展示、使用、或其他有权处理该些标识的行为。由于您违反本协议使用本公司上述商标、标识等给本公司或他人造成损失的,由您承担全部法律责任。</p>
|
||||||
|
<p><strong><em><u>7.2</u></em></strong><strong><em><u>种草短剧</u></em></strong><strong><em><u>为履行本协议而向您提供的所有素材(包括但不限于视频、文字等,以种草短剧</u></em></strong><strong><em><u>实际提供的为准),其所有知识产权归种草短剧</u></em></strong><strong><em><u>或原权利人所有。您仅可以为履行本协议之目的按种草短剧</u></em></strong><strong><em><u>认可的内容、方式和范围等使用上述素材,未经种草短剧</u></em></strong><strong><em><u>许可,不得以任何形式允许(包括但不限于转让、授权)第三方使用。否则由此导致的一切责任与后果由您承担,如因此给种草短剧</u></em></strong><strong><em><u>、种草短剧</u></em></strong><strong><em><u>合作方(如合作艺人、达人等)等造成任何损失的,您应负责全额赔偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>7.3 </u></em></strong><strong><em><u>您理解并同意,若后续您在使用种草短剧</u></em></strong><strong><em><u>平台提供的服务时需要上传、提交或存储的内容(包括但不限于文字、图片、视频、音频、动画等),您需保证签署内容均由您原创或已获合法授权,您的上述操作行为不会侵犯他人的知识产权或其他合法权益。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>您同意,因您通过种草短剧</u></em></strong><strong><em><u>平台上操作的任何内容导致的知识产权侵权问题,您将承担全部责任;如种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司因第三方知识产权维权而产生损失,您应全额赔偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>7.4</u></em></strong><strong><em><u>您知悉、理解并同意,您一旦接受本服务协议,即表明您主动将上述用户生成内容的非专属、可转让的财产性权利,如著作权(包括但不限于:复制权、发行权、出租权、展览权、表演权、放映权、广播权、信息网络传播权、摄制权、改编权、翻译权、汇编权以及应当由著作权人享有的其他可转让权利),在全世界范围内永久、免费且不可撤销地授权给种草短剧</u></em></strong><strong><em><u>及其关联公司,种草短剧</u></em></strong><strong><em><u>及其关联公司可基于该等授权使用上述内容(包括但不限于用于商业用途)或向第三方自主进行任何必要的转授权。如该等内容并非您原创,则您承诺您已获得合法授权对种草短剧</u></em></strong><strong><em><u>及其关联公司进行前述授权。该等授权、转授权的使用场景包括但不限于当前或其他任何网站、应用程序、产品或移动终端设备等,且种草短剧</u></em></strong><strong><em><u>及其关联公司或种草短剧</u></em></strong><strong><em><u>及其关联公司所授权许可的第三方可通过对上述授权内容进行修改、复制、改编、翻译、汇编或制作,形成衍生产品。在不违反相关法律法规的强制性规定、尊重相关原始授权内容的知识产权的基础上,该等衍生产品的相关知识产权归种草短剧</u></em></strong><strong><em><u>及其关联公司或种草短剧</u></em></strong><strong><em><u>所授权许可的第三方所有。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>您确认并同意授权种草短剧</u></em></strong><strong><em><u>及其关联公司以自己的名义或委托专业第三方针对有关您上传、提交、存储或发布的内容(含衍生作品)的侵权行为进行独立自主的维权并获得全部赔偿。维权形式包括但不限于:监测侵权行为、发送维权函、提起诉讼或仲裁、调解、和解等。种草短剧</u></em></strong><strong><em><u>及其关联公司有权对维权事宜做出独立决策并予以实施。</u></em></strong></p>
|
||||||
|
<p><strong>8</strong><strong>、 </strong><strong>用户的违约及处理</strong></p>
|
||||||
|
<p>8.1 发生如下情形之一的,视为您违约:</p>
|
||||||
|
<p>(1)使用种草短剧平台服务时违反有关法律法规规定的;</p>
|
||||||
|
<p>(2)违反本协议或本协议补充协议(若有)约定的的内容。</p>
|
||||||
|
<p>您理解并同意,种草短剧可在种草短剧平台规则中约定违约认定的程序和标准。</p>
|
||||||
|
<p><strong><em><u>8.2 </u></em></strong><strong><em><u>违约处理措施</u></em></strong></p>
|
||||||
|
<p><strong><em><u>信息处理:您在种草短剧</u></em></strong><strong><em><u>平台上的任何行为构成违约的,种草短剧</u></em></strong><strong><em><u>可立即对相应信息进行删除、屏蔽处理,并通过合适的形式通知您。若删除操作必须由您本人操作完成,则您应在接到平台通知后立即删除相应信息。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>行为限制:您在种草短剧</u></em></strong><strong><em><u>平台上实施的行为,或虽未在种草短剧</u></em></strong><strong><em><u>平台上实施但对种草短剧</u></em></strong><strong><em><u>平台及其用户产生影响的行为构成违约的,种草短剧</u></em></strong><strong><em><u>有权做出独立判断并采取暂停提供部分或全部服务、冻结账户内余额、查封或注销账户、终止提供服务等措施,且无需因此对您进行任何赔偿或补偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>8.3 </u></em></strong><strong><em><u>赔偿责任</u></em></strong></p>
|
||||||
|
<p><strong><em><u>如您的行为使种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司遭受损失(包括自身的直接经济损失、商誉损失及对外支付的赔偿金、和解款、律师费、诉讼费等间接经济损失),您应赔偿种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司的上述全部损失。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>如您的行为使种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司遭受第三人主张权利,种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司可在对第三人承担金钱给付等义务后就全部损失向您追偿。</u></em></strong></p>
|
||||||
|
<p><strong><em><u>如因您的行为使得第三人遭受损失或您怠于履行调处决定,种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司出于社会公共利益保护或消费者权益保护目的,可先行代您支付上述款项,您应当返还该部分费用并赔偿因此造成种草短剧</u></em></strong><strong><em><u>的全部损失。种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或关联公司也可直接抵减您在种草短剧</u></em></strong><strong><em><u>及/</u></em></strong><strong><em><u>或其关联公司其它协议项下的权益,并可继续追偿。</u></em></strong></p>
|
||||||
|
<p><strong>9</strong><strong>、 </strong><strong>通知</strong></p>
|
||||||
|
<p>9.1 有效联系方式</p>
|
||||||
|
<p>您理解并同意,种草短剧可以通过电子邮件、站内信息、手机短信、网站公告或其他方式向您发送活动信息、推广信息等各类信息。<strong><u>对于联系方式发生变更的,您有义务及时更新有关信息,并保持可被联系的状态。</u></strong><strong><u> </u></strong></p>
|
||||||
|
<p>9.2 通知的送达</p>
|
||||||
|
<p>种草短剧通过上述联系方式向您发出通知,其中以电子的方式发出的书面通知,包括但不限于在种草短剧平台显著位置刊登电子信息,向您提供的联系电话发送手机短信,向您提供的电子邮件地址发送电子邮件,向您的账户发送系统消息或站内信信息,在发送成功或刊登完成后即视为送达;以纸质载体发出的书面通知,按照提供联系地址交邮后的第五个自然日即视为送达。</p>
|
||||||
|
<p>上述送达方式同样可适用于相关仲裁或司法程序(含起诉、审理、执行等各阶段)。您应当保证所提供的联系方式是准确、有效的,并进行实时更新。如果因提供的联系方式不确切,或不及时告知变更后的联系方式,或其他不可归责于种草短剧的原因,使相关通知、文件、法律文书无法送达或未及时送达,由您自行承担由此可能产生的法律后果。</p>
|
||||||
|
<p><strong>10</strong><strong>、 </strong><strong>协议的终止</strong></p>
|
||||||
|
<p>10.1 终止的情形</p>
|
||||||
|
<p>用户发起的终止:您有权通过以下任一方式终止本协议:</p>
|
||||||
|
<p>(一)变更事项生效前您停止使用种草短剧服务并持续不再使用的;</p>
|
||||||
|
<p>(二)您明示不愿继续使用种草短剧服务,且符合种草短剧平台终止条件的。</p>
|
||||||
|
<p>种草短剧发起的终止:出现以下情况时,种草短剧可以本协议第9条的所列的方式通知您终止本协议:</p>
|
||||||
|
<p>(1)您违反本协议约定,种草短剧依据违约条款终止本协议的;</p>
|
||||||
|
<p>(2)您存在盗用他人账户、发布违禁信息、骗取他人财物、扰乱市场秩序、采取不正当手段谋利、侵犯他人合法权益等行为,种草短剧依据种草短剧平台规则对您的账户予以查封的;</p>
|
||||||
|
<p>(3)除上述情形外,因您多次违反种草短剧平台规则相关规定且情节严重,种草短剧依据种草短剧平台规则对您的账户予以查封的;</p>
|
||||||
|
<p>(4)种草短剧平台根据自身商业安排经过合理的提前通知终止全部种草短剧平台服务的;</p>
|
||||||
|
<p>(5)其它应当终止服务的情况。</p>
|
||||||
|
<p><strong>10.2 </strong><strong>协议终止后的处理</strong></p>
|
||||||
|
<p><strong>10.2.1 </strong><strong>服务终止:本协议终止后,种草短剧</strong><strong>平台将无法继续向您提供任何服务或履行任何其他义务,包括但不限于为您保留或向您披露其原种草短剧</strong><strong>账户中的任何信息,向您或第三方转发任何未曾阅读或发送过的信息等。 </strong></p>
|
||||||
|
<p><strong>10.2.2 </strong><strong>本协议终止后,种草短剧</strong><strong>仍享有下列权利:</strong></p>
|
||||||
|
<p><strong>(一)根据本协议及种草短剧</strong><strong>平台《隐私权政策》的相关约定,继续保存您留存于种草短剧</strong><strong>平台的各类信息;</strong></p>
|
||||||
|
<p><strong>(二)对于您过往的违约行为,种草短剧</strong><strong>仍可依据本协议向您追究违约责任。</strong></p>
|
||||||
|
<p>11、其他</p>
|
||||||
|
<p>11.1本协议之成立、生效、履行、解释及争议、纠纷解决,适用中华人民共和国大陆地区法律(不包括冲突法)。您同意因本协议引起的或与本协议有关的任何争议或纠纷在无法协商一致时,可向<strong><em><u>浙江省杭州市余杭区人民法院</u></em></strong>起诉,通过诉讼方式解决。</p>
|
||||||
|
<p>11.2本协议之任何部分与相关法律法规相抵触,则该部分条款应按法律法规规定重新解释。本协议部分条款之无效或重新解释不影响其它条款之法律效力。</p>
|
||||||
|
<p>11.3本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议条款解释的依据。</p>
|
||||||
|
<p>11.4本协议条款无论因何种原因部分无效或不可执行,其余条款仍有效,对双方具有约束力。</p></div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,44 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import {
|
||||||
|
loginByOpenid
|
||||||
|
} from '@/api/index'
|
||||||
|
|
||||||
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
const store = new Vuex.Store({
|
||||||
|
state: {
|
||||||
|
token: uni.getStorageSync("token") || '',
|
||||||
|
userInfo: {},
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
setToken(state, token) {
|
||||||
|
state.token = token;
|
||||||
|
uni.setStorageSync("token", token)
|
||||||
|
},
|
||||||
|
setUserInfo(state, userInfo) {
|
||||||
|
console.log(userInfo);
|
||||||
|
state.token = userInfo.openId;
|
||||||
|
uni.setStorageSync("token", userInfo.openId);
|
||||||
|
state.userInfo = userInfo;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
async getUserInfo({
|
||||||
|
commit,
|
||||||
|
state
|
||||||
|
}) {
|
||||||
|
if(!state.token) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const res = await loginByOpenid({openid: state.token})
|
||||||
|
if(res.success) {
|
||||||
|
commit('setUserInfo', res.data);
|
||||||
|
} else {
|
||||||
|
commit('setToken', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default store
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
@import "@/uni_modules/uview-ui/theme.scss";
|
||||||
|
|
||||||
|
/* 行为相关颜色 */
|
||||||
|
$uni-color-primary: #007aff;
|
||||||
|
$uni-color-success: #4cd964;
|
||||||
|
$uni-color-warning: #f0ad4e;
|
||||||
|
$uni-color-error: #dd524d;
|
||||||
|
|
||||||
|
/* 文字基本颜色 */
|
||||||
|
$uni-text-color:#333;//基本色
|
||||||
|
$uni-text-color-inverse:#fff;//反色
|
||||||
|
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||||
|
$uni-text-color-placeholder: #808080;
|
||||||
|
$uni-text-color-disable:#c0c0c0;
|
||||||
|
|
||||||
|
/* 背景颜色 */
|
||||||
|
$uni-bg-color:#ffffff;
|
||||||
|
$uni-bg-color-grey:#f8f8f8;
|
||||||
|
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||||
|
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||||
|
|
||||||
|
/* 边框颜色 */
|
||||||
|
$uni-border-color:#c8c7cc;
|
||||||
|
|
||||||
|
/* 尺寸变量 */
|
||||||
|
|
||||||
|
/* 文字尺寸 */
|
||||||
|
$uni-font-size-sm:24rpx;
|
||||||
|
$uni-font-size-base:28rpx;
|
||||||
|
$uni-font-size-lg:32rpx;
|
||||||
|
|
||||||
|
/* 图片尺寸 */
|
||||||
|
$uni-img-size-sm:40rpx;
|
||||||
|
$uni-img-size-base:52rpx;
|
||||||
|
$uni-img-size-lg:80rpx;
|
||||||
|
|
||||||
|
/* Border Radius */
|
||||||
|
$uni-border-radius-sm: 4rpx;
|
||||||
|
$uni-border-radius-base: 6rpx;
|
||||||
|
$uni-border-radius-lg: 12rpx;
|
||||||
|
$uni-border-radius-circle: 50%;
|
||||||
|
|
||||||
|
/* 水平间距 */
|
||||||
|
$uni-spacing-row-sm: 10px;
|
||||||
|
$uni-spacing-row-base: 20rpx;
|
||||||
|
$uni-spacing-row-lg: 30rpx;
|
||||||
|
|
||||||
|
/* 垂直间距 */
|
||||||
|
$uni-spacing-col-sm: 8rpx;
|
||||||
|
$uni-spacing-col-base: 16rpx;
|
||||||
|
$uni-spacing-col-lg: 24rpx;
|
||||||
|
|
||||||
|
/* 透明度 */
|
||||||
|
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||||
|
|
||||||
|
/* 文章场景相关 */
|
||||||
|
$uni-color-title: #2C405A; // 文章标题颜色
|
||||||
|
$uni-font-size-title:40rpx;
|
||||||
|
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||||
|
$uni-font-size-subtitle:36rpx;
|
||||||
|
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||||
|
$uni-font-size-paragraph:30rpx;
|
||||||
|
|
||||||
|
|
||||||
|
$uni-theme: #007aff;
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
## 1.0.1(2023-07-06)
|
||||||
|
组件优化
|
||||||
|
## 1.0.0(2023-07-06)
|
||||||
|
组件初始化
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<view class="loading">
|
||||||
|
<view class="bg-white">
|
||||||
|
<image :src="gifSrc" mode="aspectFit"
|
||||||
|
></image>
|
||||||
|
<text>加载中</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
// gif地址
|
||||||
|
gifSrc:{
|
||||||
|
type: String,
|
||||||
|
default:''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loading{
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
background-color: #fffaf0;
|
||||||
|
opacity: 0.99;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.bg-white{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.bg-white image{
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
display: block;
|
||||||
|
margin-top: -20px;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white text{
|
||||||
|
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
{
|
||||||
|
"id": "cc-gifLoading",
|
||||||
|
"displayName": "自定义加载loading组件 通过设置gif实现loading动画 可用于页面请求前loading",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"description": "自定义加载loading组件, 通过设置gif实现loading动画 可用于页面请求前loading",
|
||||||
|
"keywords": [
|
||||||
|
"loading",
|
||||||
|
"加载",
|
||||||
|
"加载动画",
|
||||||
|
"gif",
|
||||||
|
"gif动画"
|
||||||
|
],
|
||||||
|
"repository": "",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.8.0"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"type": "component-vue",
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": ""
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"钉钉": "y",
|
||||||
|
"快手": "y",
|
||||||
|
"飞书": "y",
|
||||||
|
"京东": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "y",
|
||||||
|
"联盟": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# cc-gifLoading
|
||||||
|
#
|
||||||
|
#### 使用方法
|
||||||
|
```使用方法
|
||||||
|
|
||||||
|
<!-- 自定义加载loading页面 v-if:true显示加载页面 false关闭加载页面 gifSrc:设置gif资源 -->
|
||||||
|
<cc-gifLoading v-if="true" gifSrc="https://cdn.pixabay.com/animation/2023/05/02/04/29/04-29-03-511_512.gif"></cc-gifLoading>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
## 1.3.7(2021-04-13)
|
||||||
|
1. 新增`mescroll-swiper-sticky.vue`的示例, 轮播吸顶菜单导航
|
||||||
|
2. 新增`mescroll-empty.vue`的示例, 单独使用空布局组件
|
||||||
|
3. 简化tabs在具体项目中的使用,并简化对应的示例
|
||||||
|
4. mescroll-uni 支持动态禁止滚动的属性 disableScroll (注: mescroll-body不支持)
|
||||||
|
-by 小瑾同学
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
.mescroll-body {
|
||||||
|
position: relative; /* 下拉刷新区域相对自身定位 */
|
||||||
|
height: auto; /* 不可固定高度,否则overflow:hidden导致无法滑动; 同时使设置的最小高生效,实现列表不满屏仍可下拉*/
|
||||||
|
overflow: hidden; /* 当有元素写在mescroll-body标签前面时,可遮住下拉刷新区域 */
|
||||||
|
box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 使sticky生效: 父元素不能overflow:hidden或者overflow:auto属性 */
|
||||||
|
.mescroll-body.mescorll-sticky{
|
||||||
|
overflow: unset !important
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 适配 iPhoneX */
|
||||||
|
@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
|
||||||
|
.mescroll-safearea {
|
||||||
|
padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,400 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="mescroll-body mescroll-render-touch"
|
||||||
|
:class="{'mescorll-sticky': sticky}"
|
||||||
|
:style="{'minHeight':minHeight, 'padding-top': padTop, 'padding-bottom': padBottom}"
|
||||||
|
@touchstart="wxsBiz.touchstartEvent"
|
||||||
|
@touchmove="wxsBiz.touchmoveEvent"
|
||||||
|
@touchend="wxsBiz.touchendEvent"
|
||||||
|
@touchcancel="wxsBiz.touchendEvent"
|
||||||
|
:change:prop="wxsBiz.propObserver"
|
||||||
|
:prop="wxsProp"
|
||||||
|
>
|
||||||
|
<!-- 状态栏 -->
|
||||||
|
<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
|
||||||
|
|
||||||
|
<view class="mescroll-body-content mescroll-wxs-content" :style="{ transform: translateY, transition: transition }" :change:prop="wxsBiz.callObserver" :prop="callProp">
|
||||||
|
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
|
||||||
|
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
|
||||||
|
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<view class="downwarp-progress mescroll-wxs-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
|
||||||
|
<view class="downwarp-tip">{{downText}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<!-- 空布局 -->
|
||||||
|
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
|
||||||
|
|
||||||
|
<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
|
||||||
|
<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
|
||||||
|
<view v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
|
||||||
|
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
|
||||||
|
<view v-show="upLoadType===1">
|
||||||
|
<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
|
||||||
|
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
|
||||||
|
</view>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效) -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 适配iPhoneX -->
|
||||||
|
<view v-if="safearea" class="mescroll-safearea"></view>
|
||||||
|
|
||||||
|
<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
|
||||||
|
<!-- <mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top> -->
|
||||||
|
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
|
||||||
|
<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<script src="../mescroll-uni/wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- app, h5使用renderjs -->
|
||||||
|
<!-- #ifdef APP-PLUS || H5 -->
|
||||||
|
<script module="renderBiz" lang="renderjs">
|
||||||
|
import renderBiz from "../mescroll-uni/wxs/renderjs.js";
|
||||||
|
export default {
|
||||||
|
mixins: [renderBiz]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 引入mescroll-uni.js,处理核心逻辑
|
||||||
|
import MeScroll from "../mescroll-uni/mescroll-uni.js";
|
||||||
|
// 引入全局配置
|
||||||
|
import GlobalOption from "../mescroll-uni/mescroll-uni-option.js";
|
||||||
|
// 引入国际化工具类
|
||||||
|
import mescrollI18n from '../mescroll-uni/mescroll-i18n.js';
|
||||||
|
// 引入回到顶部组件
|
||||||
|
import MescrollTop from "../mescroll-uni/components/mescroll-top.vue";
|
||||||
|
// 引入兼容wxs(含renderjs)写法的mixins
|
||||||
|
import WxsMixin from "../mescroll-uni/wxs/mixins.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mescroll-body 基于page滚动的下拉刷新和上拉加载组件, 支持嵌套原生组件, 性能好
|
||||||
|
* @property {Object} down 下拉刷新的参数配置
|
||||||
|
* @property {Object} up 上拉加载的参数配置
|
||||||
|
* @property {Object} i18n 国际化的参数配置
|
||||||
|
* @property {String, Number} top 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
* @property {Boolean, String} topbar 偏移量top是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
|
||||||
|
* @property {String, Number} bottom 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
* @property {Boolean} safearea 偏移量bottom是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
|
||||||
|
* @property {Boolean} fixed 是否通过fixed固定mescroll的高度, 默认true
|
||||||
|
* @property {String, Number} height 指定mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
|
||||||
|
* @property {Boolean} bottombar 底部是否偏移TabBar的高度 (仅在H5端的tab页生效)
|
||||||
|
* @property {Boolean} sticky 是否支持sticky,默认false; 当值配置true时,需避免在mescroll-body标签前面加非定位的元素,否则下拉区域无法隐藏
|
||||||
|
* @event {Function} init 初始化完成的回调
|
||||||
|
* @event {Function} down 下拉刷新的回调
|
||||||
|
* @event {Function} up 上拉加载的回调
|
||||||
|
* @event {Function} emptyclick 点击empty配置的btnText按钮回调
|
||||||
|
* @event {Function} topclick 点击回到顶部的按钮回调
|
||||||
|
* @event {Function} scroll 滚动监听 (需在 up 配置 onScroll:true 才生效)
|
||||||
|
* @example <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"> ... </mescroll-body>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'mescroll-body',
|
||||||
|
mixins: [WxsMixin],
|
||||||
|
components: {
|
||||||
|
MescrollTop
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
down: Object,
|
||||||
|
up: Object,
|
||||||
|
i18n: Object,
|
||||||
|
top: [String, Number],
|
||||||
|
topbar: [Boolean, String],
|
||||||
|
bottom: [String, Number],
|
||||||
|
safearea: Boolean,
|
||||||
|
height: [String, Number],
|
||||||
|
bottombar:{
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
sticky: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mescroll: {optDown:{},optUp:{}}, // mescroll实例
|
||||||
|
downHight: 0, //下拉刷新: 容器高度
|
||||||
|
downRate: 0, // 下拉比率(inOffset: rate<1; outOffset: rate>=1)
|
||||||
|
downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
|
||||||
|
upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了,显示END文本提示),3(没有更多了,不显示END文本提示)
|
||||||
|
isShowEmpty: false, // 是否显示空布局
|
||||||
|
isShowToTop: false, // 是否显示回到顶部按钮
|
||||||
|
windowHeight: 0, // 可使用窗口的高度
|
||||||
|
windowBottom: 0, // 可使用窗口的底部位置
|
||||||
|
statusBarHeight: 0 // 状态栏高度
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
|
||||||
|
minHeight(){
|
||||||
|
return this.toPx(this.height || '100%') + 'px'
|
||||||
|
},
|
||||||
|
// 下拉布局往下偏移的距离 (px)
|
||||||
|
numTop() {
|
||||||
|
return this.toPx(this.top)
|
||||||
|
},
|
||||||
|
padTop() {
|
||||||
|
return this.numTop + 'px';
|
||||||
|
},
|
||||||
|
// 上拉布局往上偏移 (px)
|
||||||
|
numBottom() {
|
||||||
|
return this.toPx(this.bottom);
|
||||||
|
},
|
||||||
|
padBottom() {
|
||||||
|
return this.numBottom + 'px';
|
||||||
|
},
|
||||||
|
// 是否为重置下拉的状态
|
||||||
|
isDownReset() {
|
||||||
|
return this.downLoadType === 3 || this.downLoadType === 4;
|
||||||
|
},
|
||||||
|
// 过渡
|
||||||
|
transition() {
|
||||||
|
return this.isDownReset ? 'transform 300ms' : '';
|
||||||
|
},
|
||||||
|
translateY() {
|
||||||
|
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading(){
|
||||||
|
return this.downLoadType === 3
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate(){
|
||||||
|
return 'rotate(' + 360 * this.downRate + 'deg)'
|
||||||
|
},
|
||||||
|
// 文本提示
|
||||||
|
downText(){
|
||||||
|
if(!this.mescroll) return ""; // 避免头条小程序初始化时报错
|
||||||
|
switch (this.downLoadType){
|
||||||
|
case 1: return this.mescroll.optDown.textInOffset;
|
||||||
|
case 2: return this.mescroll.optDown.textOutOffset;
|
||||||
|
case 3: return this.mescroll.optDown.textLoading;
|
||||||
|
case 4: return this.mescroll.isDownEndSuccess ? this.mescroll.optDown.textSuccess : this.mescroll.isDownEndSuccess==false ? this.mescroll.optDown.textErr : this.mescroll.optDown.textInOffset;
|
||||||
|
default: return this.mescroll.optDown.textInOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//number,rpx,upx,px,% --> px的数值
|
||||||
|
toPx(num) {
|
||||||
|
if (typeof num === 'string') {
|
||||||
|
if (num.indexOf('px') !== -1) {
|
||||||
|
if (num.indexOf('rpx') !== -1) {
|
||||||
|
// "10rpx"
|
||||||
|
num = num.replace('rpx', '');
|
||||||
|
} else if (num.indexOf('upx') !== -1) {
|
||||||
|
// "10upx"
|
||||||
|
num = num.replace('upx', '');
|
||||||
|
} else {
|
||||||
|
// "10px"
|
||||||
|
return Number(num.replace('px', ''));
|
||||||
|
}
|
||||||
|
} else if (num.indexOf('%') !== -1) {
|
||||||
|
// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
|
||||||
|
let rate = Number(num.replace('%', '')) / 100;
|
||||||
|
return this.windowHeight * rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num ? uni.upx2px(Number(num)) : 0;
|
||||||
|
},
|
||||||
|
// 点击空布局的按钮回调
|
||||||
|
emptyClick() {
|
||||||
|
this.$emit('emptyclick', this.mescroll);
|
||||||
|
},
|
||||||
|
// 点击回到顶部的按钮回调
|
||||||
|
toTopClick() {
|
||||||
|
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
|
||||||
|
this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||||
|
created() {
|
||||||
|
let vm = this;
|
||||||
|
|
||||||
|
let diyOption = {
|
||||||
|
// 下拉刷新的配置
|
||||||
|
down: {
|
||||||
|
inOffset() {
|
||||||
|
vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
outOffset() {
|
||||||
|
vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
onMoving(mescroll, rate, downHight) {
|
||||||
|
// 下拉过程中的回调,滑动过程一直在执行;
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downRate = rate; //下拉比率 (inOffset: rate<1; outOffset: rate>=1)
|
||||||
|
},
|
||||||
|
showLoading(mescroll, downHight) {
|
||||||
|
vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
beforeEndDownScroll(mescroll){
|
||||||
|
vm.downLoadType = 4;
|
||||||
|
return mescroll.optDown.beforeEndDelay // 延时结束的时长
|
||||||
|
},
|
||||||
|
endDownScroll() {
|
||||||
|
vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
if(vm.downResetTimer) {clearTimeout(vm.downResetTimer); vm.downResetTimer = null} // 移除重置倒计时
|
||||||
|
vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,避免下次inOffset不及时显示textInOffset
|
||||||
|
if(vm.downLoadType === 4) vm.downLoadType = 0
|
||||||
|
},300)
|
||||||
|
},
|
||||||
|
// 派发下拉刷新的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('down', mescroll);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上拉加载的配置
|
||||||
|
up: {
|
||||||
|
// 显示加载中的回调
|
||||||
|
showLoading() {
|
||||||
|
vm.upLoadType = 1;
|
||||||
|
},
|
||||||
|
// 显示无更多数据的回调
|
||||||
|
showNoMore() {
|
||||||
|
vm.upLoadType = 2;
|
||||||
|
},
|
||||||
|
// 隐藏上拉加载的回调
|
||||||
|
hideUpScroll(mescroll) {
|
||||||
|
vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
|
||||||
|
},
|
||||||
|
// 空布局
|
||||||
|
empty: {
|
||||||
|
onShow(isShow) {
|
||||||
|
// 显示隐藏的回调
|
||||||
|
vm.isShowEmpty = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 回到顶部
|
||||||
|
toTop: {
|
||||||
|
onShow(isShow) {
|
||||||
|
// 显示隐藏的回调
|
||||||
|
vm.isShowToTop = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 派发上拉加载的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('up', mescroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let i18nType = mescrollI18n.getType() // 当前语言类型
|
||||||
|
let i18nOption = {type: i18nType} // 国际化配置
|
||||||
|
MeScroll.extend(i18nOption, vm.i18n) // 具体页面的国际化配置
|
||||||
|
MeScroll.extend(i18nOption, GlobalOption.i18n) // 全局的国际化配置
|
||||||
|
MeScroll.extend(diyOption, i18nOption[i18nType]); // 混入国际化配置
|
||||||
|
MeScroll.extend(diyOption, {down:GlobalOption.down, up:GlobalOption.up}); // 混入全局的配置
|
||||||
|
let myOption = JSON.parse(JSON.stringify({down: vm.down,up: vm.up})); // 深拷贝,避免对props的影响
|
||||||
|
MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
|
||||||
|
|
||||||
|
// 初始化MeScroll对象
|
||||||
|
vm.mescroll = new MeScroll(myOption, true); // 传入true,标记body为滚动区域
|
||||||
|
// 挂载语言包
|
||||||
|
vm.mescroll.i18n = i18nOption;
|
||||||
|
// init回调mescroll对象
|
||||||
|
vm.$emit('init', vm.mescroll);
|
||||||
|
|
||||||
|
// 设置高度
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||||
|
if (sys.windowBottom) vm.windowBottom = sys.windowBottom;
|
||||||
|
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||||
|
// 使down的bottomOffset生效
|
||||||
|
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||||
|
|
||||||
|
// 因为使用的是page的scroll,这里需自定义scrollTo
|
||||||
|
vm.mescroll.resetScrollTo((y, t) => {
|
||||||
|
if(typeof y === 'string'){
|
||||||
|
// 滚动到指定view (y为css选择器)
|
||||||
|
setTimeout(()=>{ // 延时确保view已渲染; 不使用$nextTick
|
||||||
|
let selector;
|
||||||
|
if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
|
||||||
|
selector = '#'+y // 不带#和. 则默认为id选择器
|
||||||
|
}else{
|
||||||
|
selector = y
|
||||||
|
// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
|
||||||
|
if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
|
||||||
|
selector = y.split('>>>')[1].trim()
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
|
||||||
|
if (rect) {
|
||||||
|
let top = rect.top
|
||||||
|
top += vm.mescroll.getScrollTop()
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: top,
|
||||||
|
duration: t
|
||||||
|
})
|
||||||
|
} else{
|
||||||
|
console.error(selector + ' does not exist');
|
||||||
|
}
|
||||||
|
}).exec()
|
||||||
|
},30)
|
||||||
|
} else{
|
||||||
|
// 滚动到指定位置 (y必须为数字)
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: y,
|
||||||
|
duration: t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||||
|
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
|
||||||
|
vm.mescroll.optUp.toTop.safearea = vm.safearea;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局配置监听
|
||||||
|
uni.$on("setMescrollGlobalOption", options=>{
|
||||||
|
if(!options) return;
|
||||||
|
let i18nType = options.i18n ? options.i18n.type : null
|
||||||
|
if(i18nType && vm.mescroll.i18n.type != i18nType){
|
||||||
|
vm.mescroll.i18n.type = i18nType
|
||||||
|
mescrollI18n.setType(i18nType)
|
||||||
|
MeScroll.extend(options, vm.mescroll.i18n[i18nType])
|
||||||
|
}
|
||||||
|
if(options.down){
|
||||||
|
let down = MeScroll.extend({}, options.down)
|
||||||
|
vm.mescroll.optDown = MeScroll.extend(down, vm.mescroll.optDown)
|
||||||
|
}
|
||||||
|
if(options.up){
|
||||||
|
let up = MeScroll.extend({}, options.up)
|
||||||
|
vm.mescroll.optUp = MeScroll.extend(up, vm.mescroll.optUp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
// 注销全局配置监听
|
||||||
|
uni.$off("setMescrollGlobalOption")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "../mescroll-body/mescroll-body.css";
|
||||||
|
@import "../mescroll-uni/components/mescroll-down.css";
|
||||||
|
@import "../mescroll-uni/components/mescroll-up.css";
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*下拉刷新--标语*/
|
||||||
|
.mescroll-downwarp .downwarp-slogan{
|
||||||
|
display: block;
|
||||||
|
width: 420rpx;
|
||||||
|
height: 168rpx;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
/*下拉刷新--向下进度动画*/
|
||||||
|
.mescroll-downwarp .downwarp-progress{
|
||||||
|
display: inline-block;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
border: none;
|
||||||
|
margin: auto;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-image: url(https://www.mescroll.com/img/beibei/mescroll-progress.png);
|
||||||
|
transition: all 300ms;
|
||||||
|
}
|
||||||
|
/*下拉刷新--进度条*/
|
||||||
|
.mescroll-downwarp .downwarp-loading{
|
||||||
|
display: inline-block;
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid #FF8095;
|
||||||
|
border-bottom-color: transparent;
|
||||||
|
}
|
||||||
|
/*下拉刷新--吉祥物*/
|
||||||
|
.mescroll-downwarp .downwarp-mascot{
|
||||||
|
position: absolute;
|
||||||
|
right: 16rpx;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
animation: animMascot .6s steps(1,end) infinite;
|
||||||
|
}
|
||||||
|
@keyframes animMascot {
|
||||||
|
0% {background-image: url(https://www.mescroll.com/img/beibei/mescroll-bb1.png)}
|
||||||
|
25% {background-image: url(https://www.mescroll.com/img/beibei/mescroll-bb2.png)}
|
||||||
|
50% {background-image: url(https://www.mescroll.com/img/beibei/mescroll-bb3.png)}
|
||||||
|
75% {background-image: url(https://www.mescroll.com/img/beibei/mescroll-bb4.png)}
|
||||||
|
100% {background-image: url(https://www.mescroll.com/img/beibei/mescroll-bb1.png)}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!-- 下拉刷新区域 -->
|
||||||
|
<template>
|
||||||
|
<view v-if="mOption.use" class="mescroll-downwarp" :style="{'background':mOption.bgColor,'color':mOption.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<image class="downwarp-slogan" src="https://www.mescroll.com/img/beibei/mescroll-slogan.jpg?v=1" mode="widthFix"/>
|
||||||
|
<view v-if="isDownLoading" class="downwarp-loading mescroll-rotate"></view>
|
||||||
|
<view v-else class="downwarp-progress" :style="{'transform':downRotate}"></view>
|
||||||
|
<view class="downwarp-mascot"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
option: Object , // down的配置项
|
||||||
|
type: Number // 下拉状态(inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||||
|
mOption(){
|
||||||
|
return this.option || {}
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading(){
|
||||||
|
return this.type === 3
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate(){
|
||||||
|
return this.type === 2 ? 'rotate(180deg)' : 'rotate(0deg)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "../../../mescroll-uni/components/mescroll-down.css";
|
||||||
|
@import "./mescroll-down.css";
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,360 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="mescroll-body mescroll-render-touch"
|
||||||
|
:style="{'minHeight':minHeight, 'padding-top': padTop, 'padding-bottom': padBottom}"
|
||||||
|
:class="{'mescorll-sticky': sticky}"
|
||||||
|
@touchstart="wxsBiz.touchstartEvent"
|
||||||
|
@touchmove="wxsBiz.touchmoveEvent"
|
||||||
|
@touchend="wxsBiz.touchendEvent"
|
||||||
|
@touchcancel="wxsBiz.touchendEvent"
|
||||||
|
:change:prop="wxsBiz.propObserver"
|
||||||
|
:prop="wxsProp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- 状态栏 -->
|
||||||
|
<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
|
||||||
|
|
||||||
|
<view class="mescroll-body-content mescroll-wxs-content" :style="{ transform: translateY, transition: transition }" :change:prop="wxsBiz.callObserver" :prop="callProp">
|
||||||
|
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
|
||||||
|
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType"></mescroll-down> -->
|
||||||
|
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<image class="downwarp-slogan" src="https://www.mescroll.com/img/beibei/mescroll-slogan.jpg?v=1" mode="widthFix"/>
|
||||||
|
<view v-if="isDownLoading" class="downwarp-loading mescroll-rotate"></view>
|
||||||
|
<view v-else class="downwarp-progress" :style="{'transform':downRotate}"></view>
|
||||||
|
<view class="downwarp-mascot"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<!-- 空布局 -->
|
||||||
|
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
|
||||||
|
|
||||||
|
<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
|
||||||
|
<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
|
||||||
|
<view v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
|
||||||
|
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
|
||||||
|
<view v-show="upLoadType===1">
|
||||||
|
<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
|
||||||
|
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
|
||||||
|
</view>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部是否偏移TabBar的高度(仅H5端生效) -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 适配iPhoneX -->
|
||||||
|
<view v-if="safearea" class="mescroll-safearea"></view>
|
||||||
|
|
||||||
|
<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
|
||||||
|
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
|
||||||
|
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
|
||||||
|
<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<script src="../../mescroll-uni/wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- app, h5使用renderjs -->
|
||||||
|
<!-- #ifdef APP-PLUS || H5 -->
|
||||||
|
<script module="renderBiz" lang="renderjs">
|
||||||
|
import renderBiz from '../../mescroll-uni/wxs/renderjs.js';
|
||||||
|
export default {
|
||||||
|
mixins: [renderBiz]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MeScroll from '../../mescroll-uni/mescroll-uni.js';
|
||||||
|
import MescrollTop from '../../mescroll-uni/components/mescroll-top.vue';
|
||||||
|
import WxsMixin from '../../mescroll-uni/wxs/mixins.js';
|
||||||
|
import mescrollI18n from '../../mescroll-uni/mescroll-i18n.js';
|
||||||
|
import GlobalOption from './mescroll-uni-option.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [WxsMixin],
|
||||||
|
components: {
|
||||||
|
MescrollTop
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mescroll: null, // mescroll实例
|
||||||
|
downHight: 0, //下拉刷新: 容器高度
|
||||||
|
downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
|
||||||
|
upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了,显示END文本提示),3(没有更多了,不显示END文本提示)
|
||||||
|
isShowEmpty: false, // 是否显示空布局
|
||||||
|
isShowToTop: false, // 是否显示回到顶部按钮
|
||||||
|
windowHeight: 0, // 可使用窗口的高度
|
||||||
|
windowBottom: 0, // 可使用窗口的底部位置
|
||||||
|
statusBarHeight: 0 // 状态栏高度
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
down: Object, // 下拉刷新的参数配置
|
||||||
|
up: Object, // 上拉加载的参数配置
|
||||||
|
i18n: Object, // 国际化的参数配置
|
||||||
|
top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
topbar: [Boolean, String], // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
|
||||||
|
bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
|
||||||
|
height: [String, Number], // 指定mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
|
||||||
|
bottombar:{ // 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效)
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
sticky: Boolean // 是否支持sticky,默认false; 当值配置true时,需避免在mescroll-body标签前面加非定位的元素,否则下拉区域无法会隐藏
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
|
||||||
|
minHeight(){
|
||||||
|
return this.toPx(this.height || '100%') + 'px'
|
||||||
|
},
|
||||||
|
// 下拉布局往下偏移的距离 (px)
|
||||||
|
numTop() {
|
||||||
|
return this.toPx(this.top)
|
||||||
|
},
|
||||||
|
padTop() {
|
||||||
|
return this.numTop + 'px';
|
||||||
|
},
|
||||||
|
// 上拉布局往上偏移 (px)
|
||||||
|
numBottom() {
|
||||||
|
return this.toPx(this.bottom);
|
||||||
|
},
|
||||||
|
padBottom() {
|
||||||
|
return this.numBottom + 'px';
|
||||||
|
},
|
||||||
|
// 是否为重置下拉的状态
|
||||||
|
isDownReset() {
|
||||||
|
return this.downLoadType === 3 || this.downLoadType === 4;
|
||||||
|
},
|
||||||
|
// 过渡
|
||||||
|
transition() {
|
||||||
|
return this.isDownReset ? 'transform 300ms' : '';
|
||||||
|
},
|
||||||
|
translateY() {
|
||||||
|
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading(){
|
||||||
|
return this.downLoadType === 3
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate(){
|
||||||
|
return this.downLoadType === 2 ? 'rotate(180deg)' : 'rotate(0deg)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//number,rpx,upx,px,% --> px的数值
|
||||||
|
toPx(num) {
|
||||||
|
if (typeof num === 'string') {
|
||||||
|
if (num.indexOf('px') !== -1) {
|
||||||
|
if (num.indexOf('rpx') !== -1) {
|
||||||
|
// "10rpx"
|
||||||
|
num = num.replace('rpx', '');
|
||||||
|
} else if (num.indexOf('upx') !== -1) {
|
||||||
|
// "10upx"
|
||||||
|
num = num.replace('upx', '');
|
||||||
|
} else {
|
||||||
|
// "10px"
|
||||||
|
return Number(num.replace('px', ''));
|
||||||
|
}
|
||||||
|
} else if (num.indexOf('%') !== -1) {
|
||||||
|
// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
|
||||||
|
let rate = Number(num.replace('%', '')) / 100;
|
||||||
|
return this.windowHeight * rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num ? uni.upx2px(Number(num)) : 0;
|
||||||
|
},
|
||||||
|
// 点击空布局的按钮回调
|
||||||
|
emptyClick() {
|
||||||
|
this.$emit('emptyclick', this.mescroll);
|
||||||
|
},
|
||||||
|
// 点击回到顶部的按钮回调
|
||||||
|
toTopClick() {
|
||||||
|
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
|
||||||
|
this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||||
|
created() {
|
||||||
|
let vm = this;
|
||||||
|
|
||||||
|
let diyOption = {
|
||||||
|
// 下拉刷新的配置
|
||||||
|
down: {
|
||||||
|
inOffset() {
|
||||||
|
vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
outOffset() {
|
||||||
|
vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
onMoving(mescroll, rate, downHight) {
|
||||||
|
// 下拉过程中的回调,滑动过程一直在执行;
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
showLoading(mescroll, downHight) {
|
||||||
|
vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
endDownScroll() {
|
||||||
|
vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
if(vm.downResetTimer) {clearTimeout(vm.downResetTimer); vm.downResetTimer = null} // 移除重置倒计时
|
||||||
|
vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,避免下次inOffset不及时显示textInOffset
|
||||||
|
if(vm.downLoadType === 4) vm.downLoadType = 0
|
||||||
|
},300)
|
||||||
|
},
|
||||||
|
// 派发下拉刷新的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('down', mescroll);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上拉加载的配置
|
||||||
|
up: {
|
||||||
|
// 显示加载中的回调
|
||||||
|
showLoading() {
|
||||||
|
vm.upLoadType = 1;
|
||||||
|
},
|
||||||
|
// 显示无更多数据的回调
|
||||||
|
showNoMore() {
|
||||||
|
vm.upLoadType = 2;
|
||||||
|
},
|
||||||
|
// 隐藏上拉加载的回调
|
||||||
|
hideUpScroll(mescroll) {
|
||||||
|
vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
|
||||||
|
},
|
||||||
|
// 空布局
|
||||||
|
empty: {
|
||||||
|
onShow(isShow) {
|
||||||
|
// 显示隐藏的回调
|
||||||
|
vm.isShowEmpty = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 回到顶部
|
||||||
|
toTop: {
|
||||||
|
onShow(isShow) {
|
||||||
|
// 显示隐藏的回调
|
||||||
|
vm.isShowToTop = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 派发上拉加载的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('up', mescroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let i18nType = mescrollI18n.getType() // 当前语言类型
|
||||||
|
let i18nOption = {type: i18nType} // 国际化配置
|
||||||
|
MeScroll.extend(i18nOption, vm.i18n) // 具体页面的国际化配置
|
||||||
|
MeScroll.extend(i18nOption, GlobalOption.i18n) // 全局的国际化配置
|
||||||
|
MeScroll.extend(diyOption, i18nOption[i18nType]); // 混入国际化配置
|
||||||
|
MeScroll.extend(diyOption, {down:GlobalOption.down, up:GlobalOption.up}); // 混入全局的配置
|
||||||
|
let myOption = JSON.parse(JSON.stringify({down: vm.down,up: vm.up})); // 深拷贝,避免对props的影响
|
||||||
|
MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
|
||||||
|
|
||||||
|
// 初始化MeScroll对象
|
||||||
|
vm.mescroll = new MeScroll(myOption, true); // 传入true,标记body为滚动区域
|
||||||
|
// 挂载语言包
|
||||||
|
vm.mescroll.i18n = i18nOption;
|
||||||
|
// init回调mescroll对象
|
||||||
|
vm.$emit('init', vm.mescroll);
|
||||||
|
|
||||||
|
// 设置高度
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||||
|
if (sys.windowBottom) vm.windowBottom = sys.windowBottom;
|
||||||
|
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||||
|
// 使down的bottomOffset生效
|
||||||
|
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||||
|
|
||||||
|
// 因为使用的是page的scroll,这里需自定义scrollTo
|
||||||
|
vm.mescroll.resetScrollTo((y, t) => {
|
||||||
|
if(typeof y === 'string'){
|
||||||
|
// 滚动到指定view (y为css选择器)
|
||||||
|
setTimeout(()=>{ // 延时确保view已渲染; 不使用$nextTick
|
||||||
|
let selector;
|
||||||
|
if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
|
||||||
|
selector = '#'+y // 不带#和. 则默认为id选择器
|
||||||
|
}else{
|
||||||
|
selector = y
|
||||||
|
// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
|
||||||
|
if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
|
||||||
|
selector = y.split('>>>')[1].trim()
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
|
||||||
|
if (rect) {
|
||||||
|
let top = rect.top
|
||||||
|
top += vm.mescroll.getScrollTop()
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: top,
|
||||||
|
duration: t
|
||||||
|
})
|
||||||
|
} else{
|
||||||
|
console.error(selector + ' does not exist');
|
||||||
|
}
|
||||||
|
}).exec()
|
||||||
|
},30)
|
||||||
|
} else{
|
||||||
|
// 滚动到指定位置 (y必须为数字)
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: y,
|
||||||
|
duration: t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||||
|
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
|
||||||
|
vm.mescroll.optUp.toTop.safearea = vm.safearea;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局配置监听
|
||||||
|
uni.$on("setMescrollGlobalOption", options=>{
|
||||||
|
if(!options) return;
|
||||||
|
let i18nType = options.i18n ? options.i18n.type : null
|
||||||
|
if(i18nType && vm.mescroll.i18n.type != i18nType){
|
||||||
|
vm.mescroll.i18n.type = i18nType
|
||||||
|
mescrollI18n.setType(i18nType)
|
||||||
|
MeScroll.extend(options, vm.mescroll.i18n[i18nType])
|
||||||
|
}
|
||||||
|
if(options.down){
|
||||||
|
let down = MeScroll.extend({}, options.down)
|
||||||
|
vm.mescroll.optDown = MeScroll.extend(down, vm.mescroll.optDown)
|
||||||
|
}
|
||||||
|
if(options.up){
|
||||||
|
let up = MeScroll.extend({}, options.up)
|
||||||
|
vm.mescroll.optUp = MeScroll.extend(up, vm.mescroll.optUp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
// 注销全局配置监听
|
||||||
|
uni.$off("setMescrollGlobalOption")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "../../mescroll-body/mescroll-body.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-down.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-up.css";
|
||||||
|
@import "./components/mescroll-down.css";
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
// mescroll-uni和mescroll-body 的全局配置
|
||||||
|
const GlobalOption = {
|
||||||
|
down: {
|
||||||
|
// 其他down的配置参数也可以写,这里只展示了常用的配置:
|
||||||
|
offset: uni.upx2px(140), // 在列表顶部,下拉大于140upx,松手即可触发下拉刷新的回调
|
||||||
|
native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
|
||||||
|
},
|
||||||
|
up: {
|
||||||
|
// 其他up的配置参数也可以写,这里只展示了常用的配置:
|
||||||
|
offset: 150, // 距底部多远时,触发upCallback
|
||||||
|
toTop: {
|
||||||
|
// 回到顶部按钮,需配置src才显示
|
||||||
|
src: "https://www.mescroll.com/img/mescroll-totop.png", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
|
||||||
|
offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
|
||||||
|
right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||||
|
bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||||
|
width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||||
|
},
|
||||||
|
empty: {
|
||||||
|
use: true, // 是否显示空布局
|
||||||
|
icon: "https://www.mescroll.com/img/mescroll-empty.png" // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 国际化配置
|
||||||
|
i18n: {
|
||||||
|
// 中文
|
||||||
|
zh: {
|
||||||
|
up: {
|
||||||
|
textLoading: '加载中 ...', // 加载中的提示文本
|
||||||
|
textNoMore: '-- END --', // 没有更多数据的提示文本
|
||||||
|
empty: {
|
||||||
|
tip: '~ 暂无相关数据 ~' // 空提示
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 英文
|
||||||
|
en: {
|
||||||
|
up: {
|
||||||
|
textLoading: 'loading ...',
|
||||||
|
textNoMore: '-- END --',
|
||||||
|
empty: {
|
||||||
|
tip: '~ absolutely empty ~'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GlobalOption
|
||||||
|
|
@ -0,0 +1,437 @@
|
||||||
|
<template>
|
||||||
|
<view class="mescroll-uni-warp">
|
||||||
|
<scroll-view :id="viewId" class="mescroll-uni" :class="{'mescroll-uni-fixed':isFixed}" :style="{'height':scrollHeight,'padding-top':padTop,'padding-bottom':padBottom,'top':fixedTop,'bottom':fixedBottom}" :scroll-top="scrollTop" :scroll-with-animation="scrollAnim" @scroll="scroll" :scroll-y='scrollable' :enable-back-to-top="true" :throttle="false">
|
||||||
|
<view class="mescroll-uni-content mescroll-render-touch"
|
||||||
|
@touchstart="wxsBiz.touchstartEvent"
|
||||||
|
@touchmove="wxsBiz.touchmoveEvent"
|
||||||
|
@touchend="wxsBiz.touchendEvent"
|
||||||
|
@touchcancel="wxsBiz.touchendEvent"
|
||||||
|
:change:prop="wxsBiz.propObserver"
|
||||||
|
:prop="wxsProp">
|
||||||
|
|
||||||
|
<!-- 状态栏 -->
|
||||||
|
<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
|
||||||
|
|
||||||
|
<view class="mescroll-wxs-content" :style="{'transform': translateY, 'transition': transition}" :change:prop="wxsBiz.callObserver" :prop="callProp">
|
||||||
|
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
|
||||||
|
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType"></mescroll-down> -->
|
||||||
|
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<image class="downwarp-slogan" src="https://www.mescroll.com/img/beibei/mescroll-slogan.jpg?v=1" mode="widthFix"/>
|
||||||
|
<view v-if="isDownLoading" class="downwarp-loading mescroll-rotate"></view>
|
||||||
|
<view v-else class="downwarp-progress" :style="{'transform':downRotate}"></view>
|
||||||
|
<view class="downwarp-mascot"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<!-- 空布局 -->
|
||||||
|
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
|
||||||
|
|
||||||
|
<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
|
||||||
|
<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
|
||||||
|
<view v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
|
||||||
|
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
|
||||||
|
<view v-show="upLoadType===1">
|
||||||
|
<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
|
||||||
|
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
|
||||||
|
</view>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部是否偏移TabBar的高度(仅H5端生效) -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 适配iPhoneX -->
|
||||||
|
<view v-if="safearea" class="mescroll-safearea"></view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
|
||||||
|
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
|
||||||
|
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
|
||||||
|
<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<script src="../../mescroll-uni/wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- app, h5使用renderjs -->
|
||||||
|
<!-- #ifdef APP-PLUS || H5 -->
|
||||||
|
<script module="renderBiz" lang="renderjs">
|
||||||
|
import renderBiz from '../../mescroll-uni/wxs/renderjs.js';
|
||||||
|
export default {
|
||||||
|
mixins: [renderBiz]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MeScroll from '../../mescroll-uni/mescroll-uni.js';
|
||||||
|
import MescrollTop from '../../mescroll-uni/components/mescroll-top.vue';
|
||||||
|
import WxsMixin from '../../mescroll-uni/wxs/mixins.js';
|
||||||
|
import mescrollI18n from '../../mescroll-uni/mescroll-i18n.js';
|
||||||
|
import GlobalOption from './mescroll-uni-option.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [WxsMixin],
|
||||||
|
components: {
|
||||||
|
MescrollTop
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mescroll: null, // mescroll实例
|
||||||
|
viewId: 'id_' + Math.random().toString(36).substr(2,16), // 随机生成mescroll的id(不能数字开头,否则找不到元素)
|
||||||
|
downHight: 0, //下拉刷新: 容器高度
|
||||||
|
downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
|
||||||
|
upLoadType: 0, // 上拉加载状态: 0(loading前), 1loading中, 2没有更多了,显示END文本提示, 3(没有更多了,不显示END文本提示)
|
||||||
|
isShowEmpty: false, // 是否显示空布局
|
||||||
|
isShowToTop: false, // 是否显示回到顶部按钮
|
||||||
|
scrollTop: 0, // 滚动条的位置
|
||||||
|
scrollAnim: false, // 是否开启滚动动画
|
||||||
|
windowTop: 0, // 可使用窗口的顶部位置
|
||||||
|
windowBottom: 0, // 可使用窗口的底部位置
|
||||||
|
windowHeight: 0, // 可使用窗口的高度
|
||||||
|
statusBarHeight: 0 // 状态栏高度
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
down: Object, // 下拉刷新的参数配置
|
||||||
|
up: Object, // 上拉加载的参数配置
|
||||||
|
i18n: Object, // 国际化的参数配置
|
||||||
|
top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
topbar: [Boolean, String], // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
|
||||||
|
bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
|
||||||
|
fixed: { // 是否通过fixed固定mescroll的高度, 默认true
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
height: [String, Number], // 指定mescroll的高度, 此项有值,则不使用fixed. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
bottombar:{ // 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效)
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
disableScroll: Boolean // 是否禁止滚动
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 是否使用fixed定位 (当height有值,则不使用)
|
||||||
|
isFixed(){
|
||||||
|
return !this.height && this.fixed
|
||||||
|
},
|
||||||
|
// mescroll的高度
|
||||||
|
scrollHeight(){
|
||||||
|
if (this.isFixed) {
|
||||||
|
return "auto"
|
||||||
|
} else if(this.height){
|
||||||
|
return this.toPx(this.height) + 'px'
|
||||||
|
}else{
|
||||||
|
return "100%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 下拉布局往下偏移的距离 (px)
|
||||||
|
numTop() {
|
||||||
|
return this.toPx(this.top)
|
||||||
|
},
|
||||||
|
fixedTop() {
|
||||||
|
return this.isFixed ? (this.numTop + this.windowTop) + 'px' : 0
|
||||||
|
},
|
||||||
|
padTop() {
|
||||||
|
return !this.isFixed ? this.numTop + 'px' : 0
|
||||||
|
},
|
||||||
|
// 上拉布局往上偏移 (px)
|
||||||
|
numBottom() {
|
||||||
|
return this.toPx(this.bottom)
|
||||||
|
},
|
||||||
|
fixedBottom() {
|
||||||
|
return this.isFixed ? (this.numBottom + this.windowBottom) + 'px' : 0
|
||||||
|
},
|
||||||
|
padBottom() {
|
||||||
|
return !this.isFixed ? this.numBottom + 'px' : 0
|
||||||
|
},
|
||||||
|
// 是否为重置下拉的状态
|
||||||
|
isDownReset(){
|
||||||
|
return this.downLoadType===3 || this.downLoadType===4
|
||||||
|
},
|
||||||
|
// 过渡
|
||||||
|
transition() {
|
||||||
|
return this.isDownReset ? 'transform 300ms' : ''
|
||||||
|
},
|
||||||
|
translateY() {
|
||||||
|
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : '' // transform会使fixed失效,需注意把fixed元素写在mescroll之外
|
||||||
|
},
|
||||||
|
// 列表是否可滑动
|
||||||
|
scrollable(){
|
||||||
|
if(this.disableScroll) return false
|
||||||
|
return this.downLoadType===0 || this.isDownReset
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading(){
|
||||||
|
return this.downLoadType === 3
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate(){
|
||||||
|
return this.downLoadType === 2 ? 'rotate(180deg)' : 'rotate(0deg)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//number,rpx,upx,px,% --> px的数值
|
||||||
|
toPx(num){
|
||||||
|
if(typeof num === "string"){
|
||||||
|
if (num.indexOf('px') !== -1) {
|
||||||
|
if(num.indexOf('rpx') !== -1) { // "10rpx"
|
||||||
|
num = num.replace('rpx', '');
|
||||||
|
} else if(num.indexOf('upx') !== -1) { // "10upx"
|
||||||
|
num = num.replace('upx', '');
|
||||||
|
} else { // "10px"
|
||||||
|
return Number(num.replace('px', ''))
|
||||||
|
}
|
||||||
|
}else if (num.indexOf('%') !== -1){
|
||||||
|
// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
|
||||||
|
let rate = Number(num.replace("%","")) / 100
|
||||||
|
return this.windowHeight * rate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num ? uni.upx2px(Number(num)) : 0
|
||||||
|
},
|
||||||
|
//注册列表滚动事件,用于下拉刷新和上拉加载
|
||||||
|
scroll(e) {
|
||||||
|
this.mescroll.scroll(e.detail, () => {
|
||||||
|
this.$emit('scroll', this.mescroll) // 此时可直接通过 this.mescroll.scrollTop获取滚动条位置; this.mescroll.isScrollUp获取是否向上滑动
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 点击空布局的按钮回调
|
||||||
|
emptyClick() {
|
||||||
|
this.$emit('emptyclick', this.mescroll)
|
||||||
|
},
|
||||||
|
// 点击回到顶部的按钮回调
|
||||||
|
toTopClick() {
|
||||||
|
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
|
||||||
|
this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
|
||||||
|
},
|
||||||
|
// 更新滚动区域的高度 (使内容不满屏和到底,都可继续翻页)
|
||||||
|
setClientHeight() {
|
||||||
|
if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
|
||||||
|
this.isExec = true; // 避免多次获取
|
||||||
|
this.$nextTick(() => { // 确保dom已渲染
|
||||||
|
this.getClientInfo(data=>{
|
||||||
|
this.isExec = false;
|
||||||
|
if (data) {
|
||||||
|
this.mescroll.setClientHeight(data.height);
|
||||||
|
} else if (this.clientNum != 3) { // 极少部分情况,可能dom还未渲染完毕,递归获取,最多重试3次
|
||||||
|
this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setClientHeight()
|
||||||
|
}, this.clientNum * 100)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取滚动区域的信息
|
||||||
|
getClientInfo(success){
|
||||||
|
let query = uni.createSelectorQuery();
|
||||||
|
// #ifndef MP-ALIPAY || MP-DINGTALK
|
||||||
|
query = query.in(this) // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
|
||||||
|
// #endif
|
||||||
|
let view = query.select('#' + this.viewId);
|
||||||
|
view.boundingClientRect(data => {
|
||||||
|
success(data)
|
||||||
|
}).exec();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||||
|
created() {
|
||||||
|
let vm = this;
|
||||||
|
|
||||||
|
let diyOption = {
|
||||||
|
// 下拉刷新的配置
|
||||||
|
down: {
|
||||||
|
inOffset() {
|
||||||
|
vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
outOffset() {
|
||||||
|
vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
onMoving(mescroll, rate, downHight) {
|
||||||
|
// 下拉过程中的回调,滑动过程一直在执行;
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
showLoading(mescroll, downHight) {
|
||||||
|
vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
endDownScroll() {
|
||||||
|
vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downResetTimer && clearTimeout(vm.downResetTimer)
|
||||||
|
vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,以便置空this.transition,避免iOS小程序列表渲染不完整
|
||||||
|
if(vm.downLoadType===4) vm.downLoadType = 0
|
||||||
|
},300)
|
||||||
|
},
|
||||||
|
// 派发下拉刷新的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('down', mescroll)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上拉加载的配置
|
||||||
|
up: {
|
||||||
|
// 显示加载中的回调
|
||||||
|
showLoading() {
|
||||||
|
vm.upLoadType = 1;
|
||||||
|
},
|
||||||
|
// 显示无更多数据的回调
|
||||||
|
showNoMore() {
|
||||||
|
vm.upLoadType = 2;
|
||||||
|
},
|
||||||
|
// 隐藏上拉加载的回调
|
||||||
|
hideUpScroll(mescroll) {
|
||||||
|
vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
|
||||||
|
},
|
||||||
|
// 空布局
|
||||||
|
empty: {
|
||||||
|
onShow(isShow) { // 显示隐藏的回调
|
||||||
|
vm.isShowEmpty = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 回到顶部
|
||||||
|
toTop: {
|
||||||
|
onShow(isShow) { // 显示隐藏的回调
|
||||||
|
vm.isShowToTop = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 派发上拉加载的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('up', mescroll);
|
||||||
|
// 更新容器的高度 (多mescroll的情况)
|
||||||
|
vm.setClientHeight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let i18nType = mescrollI18n.getType() // 当前语言类型
|
||||||
|
let i18nOption = {type: i18nType} // 国际化配置
|
||||||
|
MeScroll.extend(i18nOption, vm.i18n) // 具体页面的国际化配置
|
||||||
|
MeScroll.extend(i18nOption, GlobalOption.i18n) // 全局的国际化配置
|
||||||
|
MeScroll.extend(diyOption, i18nOption[i18nType]); // 混入国际化配置
|
||||||
|
MeScroll.extend(diyOption, {down:GlobalOption.down, up:GlobalOption.up}); // 混入全局的配置
|
||||||
|
let myOption = JSON.parse(JSON.stringify({'down': vm.down,'up': vm.up})) // 深拷贝,避免对props的影响
|
||||||
|
MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
|
||||||
|
|
||||||
|
// 初始化MeScroll对象
|
||||||
|
vm.mescroll = new MeScroll(myOption);
|
||||||
|
vm.mescroll.viewId = vm.viewId; // 附带id
|
||||||
|
// 挂载语言包
|
||||||
|
vm.mescroll.i18n = i18nOption;
|
||||||
|
// init回调mescroll对象
|
||||||
|
vm.$emit('init', vm.mescroll);
|
||||||
|
|
||||||
|
// 设置高度
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
if(sys.windowTop) vm.windowTop = sys.windowTop;
|
||||||
|
if(sys.windowBottom) vm.windowBottom = sys.windowBottom;
|
||||||
|
if(sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||||
|
if(sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||||
|
// 使down的bottomOffset生效
|
||||||
|
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||||
|
|
||||||
|
// 因为使用的是scrollview,这里需自定义scrollTo
|
||||||
|
vm.mescroll.resetScrollTo((y, t) => {
|
||||||
|
vm.scrollAnim = (t !== 0); // t为0,则不使用动画过渡
|
||||||
|
if(typeof y === 'string'){
|
||||||
|
// 小程序不支持slot里面的scroll-into-view, 统一使用计算的方式实现
|
||||||
|
vm.getClientInfo(function(rect){
|
||||||
|
let mescrollTop = rect.top // mescroll到顶部的距离
|
||||||
|
let selector;
|
||||||
|
if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
|
||||||
|
selector = '#'+y // 不带#和. 则默认为id选择器
|
||||||
|
}else{
|
||||||
|
selector = y
|
||||||
|
// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
|
||||||
|
if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
|
||||||
|
selector = y.split('>>>')[1].trim()
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
|
||||||
|
if (rect) {
|
||||||
|
let curY = vm.mescroll.getScrollTop()
|
||||||
|
let top = rect.top - mescrollTop
|
||||||
|
top += curY
|
||||||
|
if(!vm.isFixed) top -= vm.numTop
|
||||||
|
vm.scrollTop = curY;
|
||||||
|
vm.$nextTick(function() {
|
||||||
|
vm.scrollTop = top
|
||||||
|
})
|
||||||
|
} else{
|
||||||
|
console.error(selector + ' does not exist');
|
||||||
|
}
|
||||||
|
}).exec()
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let curY = vm.mescroll.getScrollTop()
|
||||||
|
if (t === 0 || t === 300) { // 当t使用默认配置的300时,则使用系统自带的动画过渡
|
||||||
|
vm.scrollTop = curY;
|
||||||
|
vm.$nextTick(function() {
|
||||||
|
vm.scrollTop = y
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
vm.mescroll.getStep(curY, y, step => { // 此写法可支持配置t
|
||||||
|
vm.scrollTop = step
|
||||||
|
}, t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||||
|
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
|
||||||
|
vm.mescroll.optUp.toTop.safearea = vm.safearea;
|
||||||
|
}
|
||||||
|
// 全局配置监听
|
||||||
|
uni.$on("setMescrollGlobalOption", options=>{
|
||||||
|
if(!options) return;
|
||||||
|
let i18nType = options.i18n ? options.i18n.type : null
|
||||||
|
if(i18nType && vm.mescroll.i18n.type != i18nType){
|
||||||
|
vm.mescroll.i18n.type = i18nType
|
||||||
|
mescrollI18n.setType(i18nType)
|
||||||
|
MeScroll.extend(options, vm.mescroll.i18n[i18nType])
|
||||||
|
}
|
||||||
|
if(options.down){
|
||||||
|
let down = MeScroll.extend({}, options.down)
|
||||||
|
vm.mescroll.optDown = MeScroll.extend(down, vm.mescroll.optDown)
|
||||||
|
}
|
||||||
|
if(options.up){
|
||||||
|
let up = MeScroll.extend({}, options.up)
|
||||||
|
vm.mescroll.optUp = MeScroll.extend(up, vm.mescroll.optUp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 设置容器的高度
|
||||||
|
this.setClientHeight()
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
// 注销全局配置监听
|
||||||
|
uni.$off("setMescrollGlobalOption")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "../../mescroll-uni/mescroll-uni.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-down.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-up.css";
|
||||||
|
@import "./components/mescroll-down.css";
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*下拉刷新--上下箭头*/
|
||||||
|
.mescroll-downwarp .downwarp-arrow {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 10px;
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-arrow.png);
|
||||||
|
background-size: contain;
|
||||||
|
vertical-align: middle;
|
||||||
|
transition: all 300ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*下拉刷新--旋转进度条*/
|
||||||
|
.mescroll-downwarp .downwarp-progress{
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border: none;
|
||||||
|
margin: auto;
|
||||||
|
background-size: contain;
|
||||||
|
animation: progressRotate 0.6s steps(6, start) infinite;
|
||||||
|
}
|
||||||
|
@keyframes progressRotate {
|
||||||
|
0% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress1.png);
|
||||||
|
}
|
||||||
|
16% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress2.png);
|
||||||
|
}
|
||||||
|
32% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress3.png);
|
||||||
|
}
|
||||||
|
48% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress4.png);
|
||||||
|
}
|
||||||
|
64% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress5.png);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress6.png);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress1.png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<!-- 下拉刷新区域 -->
|
||||||
|
<template>
|
||||||
|
<view v-if="mOption.use" class="mescroll-downwarp" :style="{'background':mOption.bgColor,'color':mOption.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<view v-if="isDownLoading" class="downwarp-progress"></view>
|
||||||
|
<view v-else class="downwarp-arrow" :style="{ transform: downRotate }"></view>
|
||||||
|
<view class="downwarp-tip">{{ downText }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
option: Object, // down的配置项
|
||||||
|
type: Number // 下拉状态(inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||||
|
mOption() {
|
||||||
|
return this.option || {};
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading() {
|
||||||
|
return this.type === 3;
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate() {
|
||||||
|
return this.type === 2 ? 'rotate(-180deg)' : 'rotate(0deg)';
|
||||||
|
},
|
||||||
|
// 文本提示
|
||||||
|
downText() {
|
||||||
|
switch (this.type) {
|
||||||
|
case 1:
|
||||||
|
return this.mOption.textInOffset;
|
||||||
|
case 2:
|
||||||
|
return this.mOption.textOutOffset;
|
||||||
|
case 3:
|
||||||
|
return this.mOption.textLoading;
|
||||||
|
case 4:
|
||||||
|
return this.mOption.textLoading;
|
||||||
|
default:
|
||||||
|
return this.mOption.textInOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import '../../../mescroll-uni/components/mescroll-down.css';
|
||||||
|
@import './mescroll-down.css';
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*上拉加载--旋转进度条*/
|
||||||
|
.mescroll-upwarp .upwarp-progress {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border: none;
|
||||||
|
margin: auto;
|
||||||
|
background-size: contain;
|
||||||
|
animation: progressRotate 0.6s steps(6, start) infinite;
|
||||||
|
}
|
||||||
|
@keyframes progressRotate {
|
||||||
|
0% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress1.png);
|
||||||
|
}
|
||||||
|
16% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress2.png);
|
||||||
|
}
|
||||||
|
32% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress3.png);
|
||||||
|
}
|
||||||
|
48% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress4.png);
|
||||||
|
}
|
||||||
|
64% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress5.png);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress6.png);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-image: url(https://www.mescroll.com/img/xinlang/mescroll-progress1.png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<!-- 上拉加载区域 -->
|
||||||
|
<template>
|
||||||
|
<view class="mescroll-upwarp" :style="{'background':mOption.bgColor,'color':mOption.textColor}">
|
||||||
|
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
|
||||||
|
<view v-show="isUpLoading">
|
||||||
|
<view class="upwarp-progress mescroll-rotate"></view>
|
||||||
|
<view class="upwarp-tip">{{ mOption.textLoading }}</view>
|
||||||
|
</view>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<view v-if="isUpNoMore" class="upwarp-nodata">{{ mOption.textNoMore }}</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
option: Object, // up的配置项
|
||||||
|
type: Number // 上拉加载的状态:0(loading前),1(loading中),2(没有更多了,显示END文本提示),3(没有更多了,不显示END文本提示)
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||||
|
mOption() {
|
||||||
|
return this.option || {};
|
||||||
|
},
|
||||||
|
// 加载中
|
||||||
|
isUpLoading() {
|
||||||
|
return this.type === 1;
|
||||||
|
},
|
||||||
|
// 没有更多了
|
||||||
|
isUpNoMore() {
|
||||||
|
return this.type === 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import '../../../mescroll-uni/components/mescroll-up.css';
|
||||||
|
@import './mescroll-up.css';
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,380 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="mescroll-body mescroll-render-touch"
|
||||||
|
:style="{'minHeight':minHeight, 'padding-top': padTop, 'padding-bottom': padBottom}"
|
||||||
|
:class="{'mescorll-sticky': sticky}"
|
||||||
|
@touchstart="wxsBiz.touchstartEvent"
|
||||||
|
@touchmove="wxsBiz.touchmoveEvent"
|
||||||
|
@touchend="wxsBiz.touchendEvent"
|
||||||
|
@touchcancel="wxsBiz.touchendEvent"
|
||||||
|
:change:prop="wxsBiz.propObserver"
|
||||||
|
:prop="wxsProp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- 状态栏 -->
|
||||||
|
<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
|
||||||
|
|
||||||
|
<view class="mescroll-body-content mescroll-wxs-content" :style="{ transform: translateY, transition: transition }" :change:prop="wxsBiz.callObserver" :prop="callProp">
|
||||||
|
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
|
||||||
|
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType"></mescroll-down> -->
|
||||||
|
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<view v-if="isDownLoading" class="downwarp-progress"></view>
|
||||||
|
<view v-else class="downwarp-arrow" :style="{ transform: downRotate }"></view>
|
||||||
|
<view class="downwarp-tip">{{ downText }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<!-- 空布局 -->
|
||||||
|
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
|
||||||
|
|
||||||
|
<!-- 上拉加载区域 (下拉刷新时不显示,支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
|
||||||
|
<!-- <mescroll-up v-if="mescroll.optUp.use && downLoadType !== 3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
|
||||||
|
<view class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
|
||||||
|
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
|
||||||
|
<view v-show="upLoadType===1">
|
||||||
|
<view class="upwarp-progress mescroll-rotate"></view>
|
||||||
|
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
|
||||||
|
</view>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部是否偏移TabBar的高度(仅H5端生效) -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 适配iPhoneX -->
|
||||||
|
<view v-if="safearea" class="mescroll-safearea"></view>
|
||||||
|
|
||||||
|
<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
|
||||||
|
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
|
||||||
|
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
|
||||||
|
<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<script src="../../mescroll-uni/wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- app, h5使用renderjs -->
|
||||||
|
<!-- #ifdef APP-PLUS || H5 -->
|
||||||
|
<script module="renderBiz" lang="renderjs">
|
||||||
|
import renderBiz from '../../mescroll-uni/wxs/renderjs.js';
|
||||||
|
export default {
|
||||||
|
mixins: [renderBiz]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MeScroll from '../../mescroll-uni/mescroll-uni.js';
|
||||||
|
import MescrollTop from '../../mescroll-uni/components/mescroll-top.vue';
|
||||||
|
import WxsMixin from '../../mescroll-uni/wxs/mixins.js';
|
||||||
|
import mescrollI18n from '../../mescroll-uni/mescroll-i18n.js';
|
||||||
|
import GlobalOption from './mescroll-uni-option.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [WxsMixin],
|
||||||
|
components: {
|
||||||
|
MescrollTop
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mescroll: null, // mescroll实例
|
||||||
|
downHight: 0, //下拉刷新: 容器高度
|
||||||
|
downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
|
||||||
|
upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了,显示END文本提示),3(没有更多了,不显示END文本提示)
|
||||||
|
isShowEmpty: false, // 是否显示空布局
|
||||||
|
isShowToTop: false, // 是否显示回到顶部按钮
|
||||||
|
windowHeight: 0, // 可使用窗口的高度
|
||||||
|
windowBottom: 0, // 可使用窗口的底部位置
|
||||||
|
statusBarHeight: 0 // 状态栏高度
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
down: Object, // 下拉刷新的参数配置
|
||||||
|
up: Object, // 上拉加载的参数配置
|
||||||
|
i18n: Object, // 国际化的参数配置
|
||||||
|
top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
topbar: [Boolean, String], // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
|
||||||
|
bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
|
||||||
|
height: [String, Number], // 指定mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
|
||||||
|
bottombar:{ // 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效)
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
sticky: Boolean // 是否支持sticky,默认false; 当值配置true时,需避免在mescroll-body标签前面加非定位的元素,否则下拉区域无法会隐藏
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
|
||||||
|
minHeight(){
|
||||||
|
return this.toPx(this.height || '100%') + 'px'
|
||||||
|
},
|
||||||
|
// 下拉布局往下偏移的距离 (px)
|
||||||
|
numTop() {
|
||||||
|
return this.toPx(this.top)
|
||||||
|
},
|
||||||
|
padTop() {
|
||||||
|
return this.numTop + 'px';
|
||||||
|
},
|
||||||
|
// 上拉布局往上偏移 (px)
|
||||||
|
numBottom() {
|
||||||
|
return this.toPx(this.bottom);
|
||||||
|
},
|
||||||
|
padBottom() {
|
||||||
|
return this.numBottom + 'px';
|
||||||
|
},
|
||||||
|
// 是否为重置下拉的状态
|
||||||
|
isDownReset() {
|
||||||
|
return this.downLoadType === 3 || this.downLoadType === 4;
|
||||||
|
},
|
||||||
|
// 过渡
|
||||||
|
transition() {
|
||||||
|
return this.isDownReset ? 'transform 300ms' : '';
|
||||||
|
},
|
||||||
|
translateY() {
|
||||||
|
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading() {
|
||||||
|
return this.downLoadType === 3;
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate() {
|
||||||
|
return this.downLoadType === 2 ? 'rotate(-180deg)' : 'rotate(0deg)';
|
||||||
|
},
|
||||||
|
// 文本提示
|
||||||
|
downText() {
|
||||||
|
if(!this.mescroll) return "";
|
||||||
|
switch (this.downLoadType) {
|
||||||
|
case 1:
|
||||||
|
return this.mescroll.optDown.textInOffset;
|
||||||
|
case 2:
|
||||||
|
return this.mescroll.optDown.textOutOffset;
|
||||||
|
case 3:
|
||||||
|
return this.mescroll.optDown.textLoading;
|
||||||
|
case 4:
|
||||||
|
return this.mescroll.isDownEndSuccess ? this.mescroll.optDown.textSuccess : this.mescroll.isDownEndSuccess==false ? this.mescroll.optDown.textErr : this.mescroll.optDown.textInOffset;
|
||||||
|
default:
|
||||||
|
return this.mescroll.optDown.textInOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//number,rpx,upx,px,% --> px的数值
|
||||||
|
toPx(num) {
|
||||||
|
if (typeof num === 'string') {
|
||||||
|
if (num.indexOf('px') !== -1) {
|
||||||
|
if (num.indexOf('rpx') !== -1) {
|
||||||
|
// "10rpx"
|
||||||
|
num = num.replace('rpx', '');
|
||||||
|
} else if (num.indexOf('upx') !== -1) {
|
||||||
|
// "10upx"
|
||||||
|
num = num.replace('upx', '');
|
||||||
|
} else {
|
||||||
|
// "10px"
|
||||||
|
return Number(num.replace('px', ''));
|
||||||
|
}
|
||||||
|
} else if (num.indexOf('%') !== -1) {
|
||||||
|
// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
|
||||||
|
let rate = Number(num.replace('%', '')) / 100;
|
||||||
|
return this.windowHeight * rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num ? uni.upx2px(Number(num)) : 0;
|
||||||
|
},
|
||||||
|
// 点击空布局的按钮回调
|
||||||
|
emptyClick() {
|
||||||
|
this.$emit('emptyclick', this.mescroll);
|
||||||
|
},
|
||||||
|
// 点击回到顶部的按钮回调
|
||||||
|
toTopClick() {
|
||||||
|
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
|
||||||
|
this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||||
|
created() {
|
||||||
|
let vm = this;
|
||||||
|
|
||||||
|
let diyOption = {
|
||||||
|
// 下拉刷新的配置
|
||||||
|
down: {
|
||||||
|
inOffset() {
|
||||||
|
vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
outOffset() {
|
||||||
|
vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
onMoving(mescroll, rate, downHight) {
|
||||||
|
// 下拉过程中的回调,滑动过程一直在执行;
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
showLoading(mescroll, downHight) {
|
||||||
|
vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
beforeEndDownScroll(mescroll){
|
||||||
|
vm.downLoadType = 4;
|
||||||
|
return mescroll.optDown.beforeEndDelay // 延时结束的时长
|
||||||
|
},
|
||||||
|
endDownScroll() {
|
||||||
|
vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
if(vm.downResetTimer) {clearTimeout(vm.downResetTimer); vm.downResetTimer = null} // 移除重置倒计时
|
||||||
|
vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,避免下次inOffset不及时显示textInOffset
|
||||||
|
if(vm.downLoadType === 4) vm.downLoadType = 0
|
||||||
|
},300)
|
||||||
|
},
|
||||||
|
// 派发下拉刷新的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('down', mescroll);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上拉加载的配置
|
||||||
|
up: {
|
||||||
|
// 显示加载中的回调
|
||||||
|
showLoading() {
|
||||||
|
vm.upLoadType = 1;
|
||||||
|
},
|
||||||
|
// 显示无更多数据的回调
|
||||||
|
showNoMore() {
|
||||||
|
vm.upLoadType = 2;
|
||||||
|
},
|
||||||
|
// 隐藏上拉加载的回调
|
||||||
|
hideUpScroll(mescroll) {
|
||||||
|
vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
|
||||||
|
},
|
||||||
|
// 空布局
|
||||||
|
empty: {
|
||||||
|
onShow(isShow) {
|
||||||
|
// 显示隐藏的回调
|
||||||
|
vm.isShowEmpty = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 回到顶部
|
||||||
|
toTop: {
|
||||||
|
onShow(isShow) {
|
||||||
|
// 显示隐藏的回调
|
||||||
|
vm.isShowToTop = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 派发上拉加载的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('up', mescroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let i18nType = mescrollI18n.getType() // 当前语言类型
|
||||||
|
let i18nOption = {type: i18nType} // 国际化配置
|
||||||
|
MeScroll.extend(i18nOption, vm.i18n) // 具体页面的国际化配置
|
||||||
|
MeScroll.extend(i18nOption, GlobalOption.i18n) // 全局的国际化配置
|
||||||
|
MeScroll.extend(diyOption, i18nOption[i18nType]); // 混入国际化配置
|
||||||
|
MeScroll.extend(diyOption, {down:GlobalOption.down, up:GlobalOption.up}); // 混入全局的配置
|
||||||
|
let myOption = JSON.parse(JSON.stringify({down: vm.down,up: vm.up})); // 深拷贝,避免对props的影响
|
||||||
|
MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
|
||||||
|
|
||||||
|
// 初始化MeScroll对象
|
||||||
|
vm.mescroll = new MeScroll(myOption, true); // 传入true,标记body为滚动区域
|
||||||
|
// 挂载语言包
|
||||||
|
vm.mescroll.i18n = i18nOption;
|
||||||
|
// init回调mescroll对象
|
||||||
|
vm.$emit('init', vm.mescroll);
|
||||||
|
|
||||||
|
// 设置高度
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||||
|
if (sys.windowBottom) vm.windowBottom = sys.windowBottom;
|
||||||
|
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||||
|
// 使down的bottomOffset生效
|
||||||
|
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||||
|
|
||||||
|
// 因为使用的是page的scroll,这里需自定义scrollTo
|
||||||
|
vm.mescroll.resetScrollTo((y, t) => {
|
||||||
|
if(typeof y === 'string'){
|
||||||
|
// 滚动到指定view (y为css选择器)
|
||||||
|
setTimeout(()=>{ // 延时确保view已渲染; 不使用$nextTick
|
||||||
|
let selector;
|
||||||
|
if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
|
||||||
|
selector = '#'+y // 不带#和. 则默认为id选择器
|
||||||
|
}else{
|
||||||
|
selector = y
|
||||||
|
// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
|
||||||
|
if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
|
||||||
|
selector = y.split('>>>')[1].trim()
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
|
||||||
|
if (rect) {
|
||||||
|
let top = rect.top
|
||||||
|
top += vm.mescroll.getScrollTop()
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: top,
|
||||||
|
duration: t
|
||||||
|
})
|
||||||
|
} else{
|
||||||
|
console.error(selector + ' does not exist');
|
||||||
|
}
|
||||||
|
}).exec()
|
||||||
|
},30)
|
||||||
|
} else{
|
||||||
|
// 滚动到指定位置 (y必须为数字)
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: y,
|
||||||
|
duration: t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||||
|
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
|
||||||
|
vm.mescroll.optUp.toTop.safearea = vm.safearea;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局配置监听
|
||||||
|
uni.$on("setMescrollGlobalOption", options=>{
|
||||||
|
if(!options) return;
|
||||||
|
let i18nType = options.i18n ? options.i18n.type : null
|
||||||
|
if(i18nType && vm.mescroll.i18n.type != i18nType){
|
||||||
|
vm.mescroll.i18n.type = i18nType
|
||||||
|
mescrollI18n.setType(i18nType)
|
||||||
|
MeScroll.extend(options, vm.mescroll.i18n[i18nType])
|
||||||
|
}
|
||||||
|
if(options.down){
|
||||||
|
let down = MeScroll.extend({}, options.down)
|
||||||
|
vm.mescroll.optDown = MeScroll.extend(down, vm.mescroll.optDown)
|
||||||
|
}
|
||||||
|
if(options.up){
|
||||||
|
let up = MeScroll.extend({}, options.up)
|
||||||
|
vm.mescroll.optUp = MeScroll.extend(up, vm.mescroll.optUp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
// 注销全局配置监听
|
||||||
|
uni.$off("setMescrollGlobalOption")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "../../mescroll-uni/mescroll-uni.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-down.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-up.css";
|
||||||
|
@import "./components/mescroll-down.css";
|
||||||
|
@import "./components/mescroll-up.css";
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
// 全局配置
|
||||||
|
// mescroll-body 和 mescroll-uni 通用
|
||||||
|
const GlobalOption = {
|
||||||
|
down: {
|
||||||
|
// 其他down的配置参数也可以写,这里只展示了常用的配置:
|
||||||
|
offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
|
||||||
|
native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
|
||||||
|
},
|
||||||
|
up: {
|
||||||
|
// 其他up的配置参数也可以写,这里只展示了常用的配置:
|
||||||
|
offset: 150, // 距底部多远时,触发upCallback,仅mescroll-uni生效 ( mescroll-body配置的是pages.json的 onReachBottomDistance )
|
||||||
|
toTop: {
|
||||||
|
// 回到顶部按钮,需配置src才显示
|
||||||
|
src: "https://www.mescroll.com/img/mescroll-totop.png", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
|
||||||
|
offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
|
||||||
|
right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||||
|
bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||||
|
width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||||
|
},
|
||||||
|
empty: {
|
||||||
|
use: true, // 是否显示空布局
|
||||||
|
icon: "https://www.mescroll.com/img/mescroll-empty.png" // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 国际化配置
|
||||||
|
i18n: {
|
||||||
|
// 中文
|
||||||
|
zh: {
|
||||||
|
down: {
|
||||||
|
textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
|
||||||
|
textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
|
||||||
|
textLoading: '加载中 ...', // 加载中的提示文本
|
||||||
|
textSuccess: '加载成功', // 加载成功的文本
|
||||||
|
textErr: '加载失败', // 加载失败的文本
|
||||||
|
},
|
||||||
|
up: {
|
||||||
|
textLoading: '加载中 ...', // 加载中的提示文本
|
||||||
|
textNoMore: '-- END --', // 没有更多数据的提示文本
|
||||||
|
empty: {
|
||||||
|
tip: '~ 空空如也 ~' // 空提示
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 英文
|
||||||
|
en: {
|
||||||
|
down: {
|
||||||
|
textInOffset: 'drop down refresh',
|
||||||
|
textOutOffset: 'release updates',
|
||||||
|
textLoading: 'loading ...',
|
||||||
|
textSuccess: 'loaded successfully',
|
||||||
|
textErr: 'loading failed'
|
||||||
|
},
|
||||||
|
up: {
|
||||||
|
textLoading: 'loading ...',
|
||||||
|
textNoMore: '-- END --',
|
||||||
|
empty: {
|
||||||
|
tip: '~ absolutely empty ~'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GlobalOption
|
||||||
|
|
@ -0,0 +1,462 @@
|
||||||
|
<template>
|
||||||
|
<view class="mescroll-uni-warp">
|
||||||
|
<scroll-view :id="viewId" class="mescroll-uni" :class="{'mescroll-uni-fixed':isFixed}" :style="{'height':scrollHeight,'padding-top':padTop,'padding-bottom':padBottom,'top':fixedTop,'bottom':fixedBottom}" :scroll-top="scrollTop" :scroll-with-animation="scrollAnim" @scroll="scroll" :scroll-y='scrollable' :enable-back-to-top="true" :throttle="false">
|
||||||
|
<view class="mescroll-uni-content mescroll-render-touch"
|
||||||
|
@touchstart="wxsBiz.touchstartEvent"
|
||||||
|
@touchmove="wxsBiz.touchmoveEvent"
|
||||||
|
@touchend="wxsBiz.touchendEvent"
|
||||||
|
@touchcancel="wxsBiz.touchendEvent"
|
||||||
|
:change:prop="wxsBiz.propObserver"
|
||||||
|
:prop="wxsProp">
|
||||||
|
|
||||||
|
<!-- 状态栏 -->
|
||||||
|
<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
|
||||||
|
|
||||||
|
<view class="mescroll-wxs-content" :style="{'transform': translateY, 'transition': transition}" :change:prop="wxsBiz.callObserver" :prop="callProp">
|
||||||
|
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
|
||||||
|
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType"></mescroll-down> -->
|
||||||
|
<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<view v-if="isDownLoading" class="downwarp-progress"></view>
|
||||||
|
<view v-else class="downwarp-arrow" :style="{ transform: downRotate }"></view>
|
||||||
|
<view class="downwarp-tip">{{ downText }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<!-- 空布局 -->
|
||||||
|
<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
|
||||||
|
|
||||||
|
<!-- 上拉加载区域 (下拉刷新时不显示,支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
|
||||||
|
<!-- <mescroll-up v-if="mescroll.optUp.use && downLoadType !== 3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
|
||||||
|
<view class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
|
||||||
|
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
|
||||||
|
<view v-show="upLoadType===1">
|
||||||
|
<view class="upwarp-progress mescroll-rotate"></view>
|
||||||
|
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
|
||||||
|
</view>
|
||||||
|
<!-- 无数据 -->
|
||||||
|
<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部是否偏移TabBar的高度(仅H5端生效) -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 适配iPhoneX -->
|
||||||
|
<view v-if="safearea" class="mescroll-safearea"></view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
|
||||||
|
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
|
||||||
|
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
|
||||||
|
<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
|
||||||
|
<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
|
||||||
|
<script src="../../mescroll-uni/wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- app, h5使用renderjs -->
|
||||||
|
<!-- #ifdef APP-PLUS || H5 -->
|
||||||
|
<script module="renderBiz" lang="renderjs">
|
||||||
|
import renderBiz from '../../mescroll-uni/wxs/renderjs.js';
|
||||||
|
export default {
|
||||||
|
mixins: [renderBiz]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MeScroll from '../../mescroll-uni/mescroll-uni.js';
|
||||||
|
import MescrollTop from '../../mescroll-uni/components/mescroll-top.vue';
|
||||||
|
import WxsMixin from '../../mescroll-uni/wxs/mixins.js';
|
||||||
|
import mescrollI18n from '../../mescroll-uni/mescroll-i18n.js';
|
||||||
|
import GlobalOption from './mescroll-uni-option.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [WxsMixin],
|
||||||
|
components: {
|
||||||
|
MescrollTop
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mescroll: null, // mescroll实例
|
||||||
|
viewId: 'id_' + Math.random().toString(36).substr(2,16), // 随机生成mescroll的id(不能数字开头,否则找不到元素)
|
||||||
|
downHight: 0, //下拉刷新: 容器高度
|
||||||
|
downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
|
||||||
|
upLoadType: 0, // 上拉加载状态: 0(loading前), 1loading中, 2没有更多了,显示END文本提示, 3(没有更多了,不显示END文本提示)
|
||||||
|
isShowEmpty: false, // 是否显示空布局
|
||||||
|
isShowToTop: false, // 是否显示回到顶部按钮
|
||||||
|
scrollTop: 0, // 滚动条的位置
|
||||||
|
scrollAnim: false, // 是否开启滚动动画
|
||||||
|
windowTop: 0, // 可使用窗口的顶部位置
|
||||||
|
windowBottom: 0, // 可使用窗口的底部位置
|
||||||
|
windowHeight: 0, // 可使用窗口的高度
|
||||||
|
statusBarHeight: 0 // 状态栏高度
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
down: Object, // 下拉刷新的参数配置
|
||||||
|
up: Object, // 上拉加载的参数配置
|
||||||
|
i18n: Object, // 国际化的参数配置
|
||||||
|
top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
topbar: [Boolean, String], // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
|
||||||
|
bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
|
||||||
|
fixed: { // 是否通过fixed固定mescroll的高度, 默认true
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
height: [String, Number], // 指定mescroll的高度, 此项有值,则不使用fixed. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||||
|
bottombar:{ // 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效)
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
disableScroll: Boolean // 是否禁止滚动
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 是否使用fixed定位 (当height有值,则不使用)
|
||||||
|
isFixed(){
|
||||||
|
return !this.height && this.fixed
|
||||||
|
},
|
||||||
|
// mescroll的高度
|
||||||
|
scrollHeight(){
|
||||||
|
if (this.isFixed) {
|
||||||
|
return "auto"
|
||||||
|
} else if(this.height){
|
||||||
|
return this.toPx(this.height) + 'px'
|
||||||
|
}else{
|
||||||
|
return "100%"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 下拉布局往下偏移的距离 (px)
|
||||||
|
numTop() {
|
||||||
|
return this.toPx(this.top)
|
||||||
|
},
|
||||||
|
fixedTop() {
|
||||||
|
return this.isFixed ? (this.numTop + this.windowTop) + 'px' : 0
|
||||||
|
},
|
||||||
|
padTop() {
|
||||||
|
return !this.isFixed ? this.numTop + 'px' : 0
|
||||||
|
},
|
||||||
|
// 上拉布局往上偏移 (px)
|
||||||
|
numBottom() {
|
||||||
|
return this.toPx(this.bottom)
|
||||||
|
},
|
||||||
|
fixedBottom() {
|
||||||
|
return this.isFixed ? (this.numBottom + this.windowBottom) + 'px' : 0
|
||||||
|
},
|
||||||
|
padBottom() {
|
||||||
|
return !this.isFixed ? this.numBottom + 'px' : 0
|
||||||
|
},
|
||||||
|
// 是否为重置下拉的状态
|
||||||
|
isDownReset(){
|
||||||
|
return this.downLoadType===3 || this.downLoadType===4
|
||||||
|
},
|
||||||
|
// 过渡
|
||||||
|
transition() {
|
||||||
|
return this.isDownReset ? 'transform 300ms' : ''
|
||||||
|
},
|
||||||
|
translateY() {
|
||||||
|
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : '' // transform会使fixed失效,需注意把fixed元素写在mescroll之外
|
||||||
|
},
|
||||||
|
// 列表是否可滑动
|
||||||
|
scrollable(){
|
||||||
|
if(this.disableScroll) return false
|
||||||
|
return this.downLoadType===0 || this.isDownReset
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading() {
|
||||||
|
return this.downLoadType === 3;
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate() {
|
||||||
|
return this.downLoadType === 2 ? 'rotate(-180deg)' : 'rotate(0deg)';
|
||||||
|
},
|
||||||
|
// 文本提示
|
||||||
|
downText() {
|
||||||
|
if(!this.mescroll) return "";
|
||||||
|
switch (this.downLoadType) {
|
||||||
|
case 1:
|
||||||
|
return this.mescroll.optDown.textInOffset;
|
||||||
|
case 2:
|
||||||
|
return this.mescroll.optDown.textOutOffset;
|
||||||
|
case 3:
|
||||||
|
return this.mescroll.optDown.textLoading;
|
||||||
|
case 4:
|
||||||
|
return this.mescroll.isDownEndSuccess ? this.mescroll.optDown.textSuccess : this.mescroll.isDownEndSuccess==false ? this.mescroll.optDown.textErr : this.mescroll.optDown.textInOffset;
|
||||||
|
default:
|
||||||
|
return this.mescroll.optDown.textInOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//number,rpx,upx,px,% --> px的数值
|
||||||
|
toPx(num){
|
||||||
|
if(typeof num === "string"){
|
||||||
|
if (num.indexOf('px') !== -1) {
|
||||||
|
if(num.indexOf('rpx') !== -1) { // "10rpx"
|
||||||
|
num = num.replace('rpx', '');
|
||||||
|
} else if(num.indexOf('upx') !== -1) { // "10upx"
|
||||||
|
num = num.replace('upx', '');
|
||||||
|
} else { // "10px"
|
||||||
|
return Number(num.replace('px', ''))
|
||||||
|
}
|
||||||
|
}else if (num.indexOf('%') !== -1){
|
||||||
|
// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
|
||||||
|
let rate = Number(num.replace("%","")) / 100
|
||||||
|
return this.windowHeight * rate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num ? uni.upx2px(Number(num)) : 0
|
||||||
|
},
|
||||||
|
//注册列表滚动事件,用于下拉刷新和上拉加载
|
||||||
|
scroll(e) {
|
||||||
|
this.mescroll.scroll(e.detail, () => {
|
||||||
|
this.$emit('scroll', this.mescroll) // 此时可直接通过 this.mescroll.scrollTop获取滚动条位置; this.mescroll.isScrollUp获取是否向上滑动
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 点击空布局的按钮回调
|
||||||
|
emptyClick() {
|
||||||
|
this.$emit('emptyclick', this.mescroll)
|
||||||
|
},
|
||||||
|
// 点击回到顶部的按钮回调
|
||||||
|
toTopClick() {
|
||||||
|
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
|
||||||
|
this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
|
||||||
|
},
|
||||||
|
// 更新滚动区域的高度 (使内容不满屏和到底,都可继续翻页)
|
||||||
|
setClientHeight() {
|
||||||
|
if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
|
||||||
|
this.isExec = true; // 避免多次获取
|
||||||
|
this.$nextTick(() => { // 确保dom已渲染
|
||||||
|
this.getClientInfo(data=>{
|
||||||
|
this.isExec = false;
|
||||||
|
if (data) {
|
||||||
|
this.mescroll.setClientHeight(data.height);
|
||||||
|
} else if (this.clientNum != 3) { // 极少部分情况,可能dom还未渲染完毕,递归获取,最多重试3次
|
||||||
|
this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setClientHeight()
|
||||||
|
}, this.clientNum * 100)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取滚动区域的信息
|
||||||
|
getClientInfo(success){
|
||||||
|
let query = uni.createSelectorQuery();
|
||||||
|
// #ifndef MP-ALIPAY || MP-DINGTALK
|
||||||
|
query = query.in(this) // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
|
||||||
|
// #endif
|
||||||
|
let view = query.select('#' + this.viewId);
|
||||||
|
view.boundingClientRect(data => {
|
||||||
|
success(data)
|
||||||
|
}).exec();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||||
|
created() {
|
||||||
|
let vm = this;
|
||||||
|
|
||||||
|
let diyOption = {
|
||||||
|
// 下拉刷新的配置
|
||||||
|
down: {
|
||||||
|
inOffset() {
|
||||||
|
vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
outOffset() {
|
||||||
|
vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
onMoving(mescroll, rate, downHight) {
|
||||||
|
// 下拉过程中的回调,滑动过程一直在执行;
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
showLoading(mescroll, downHight) {
|
||||||
|
vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
},
|
||||||
|
beforeEndDownScroll(mescroll){
|
||||||
|
vm.downLoadType = 4;
|
||||||
|
return mescroll.optDown.beforeEndDelay // 延时结束的时长
|
||||||
|
},
|
||||||
|
endDownScroll() {
|
||||||
|
vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
|
||||||
|
vm.downResetTimer && clearTimeout(vm.downResetTimer)
|
||||||
|
vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,以便置空this.transition,避免iOS小程序列表渲染不完整
|
||||||
|
if(vm.downLoadType===4) vm.downLoadType = 0
|
||||||
|
},300)
|
||||||
|
},
|
||||||
|
// 派发下拉刷新的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('down', mescroll)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上拉加载的配置
|
||||||
|
up: {
|
||||||
|
// 显示加载中的回调
|
||||||
|
showLoading() {
|
||||||
|
vm.upLoadType = 1;
|
||||||
|
},
|
||||||
|
// 显示无更多数据的回调
|
||||||
|
showNoMore() {
|
||||||
|
vm.upLoadType = 2;
|
||||||
|
},
|
||||||
|
// 隐藏上拉加载的回调
|
||||||
|
hideUpScroll(mescroll) {
|
||||||
|
vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
|
||||||
|
},
|
||||||
|
// 空布局
|
||||||
|
empty: {
|
||||||
|
onShow(isShow) { // 显示隐藏的回调
|
||||||
|
vm.isShowEmpty = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 回到顶部
|
||||||
|
toTop: {
|
||||||
|
onShow(isShow) { // 显示隐藏的回调
|
||||||
|
vm.isShowToTop = isShow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 派发上拉加载的回调
|
||||||
|
callback: function(mescroll) {
|
||||||
|
vm.$emit('up', mescroll);
|
||||||
|
// 更新容器的高度 (多mescroll的情况)
|
||||||
|
vm.setClientHeight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let i18nType = mescrollI18n.getType() // 当前语言类型
|
||||||
|
let i18nOption = {type: i18nType} // 国际化配置
|
||||||
|
MeScroll.extend(i18nOption, vm.i18n) // 具体页面的国际化配置
|
||||||
|
MeScroll.extend(i18nOption, GlobalOption.i18n) // 全局的国际化配置
|
||||||
|
MeScroll.extend(diyOption, i18nOption[i18nType]); // 混入国际化配置
|
||||||
|
MeScroll.extend(diyOption, {down:GlobalOption.down, up:GlobalOption.up}); // 混入全局的配置
|
||||||
|
let myOption = JSON.parse(JSON.stringify({
|
||||||
|
'down': vm.down,
|
||||||
|
'up': vm.up
|
||||||
|
})) // 深拷贝,避免对props的影响
|
||||||
|
MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
|
||||||
|
|
||||||
|
// 初始化MeScroll对象
|
||||||
|
vm.mescroll = new MeScroll(myOption);
|
||||||
|
vm.mescroll.viewId = vm.viewId; // 附带id
|
||||||
|
// 挂载语言包
|
||||||
|
vm.mescroll.i18n = i18nOption;
|
||||||
|
// init回调mescroll对象
|
||||||
|
vm.$emit('init', vm.mescroll);
|
||||||
|
|
||||||
|
// 设置高度
|
||||||
|
const sys = uni.getSystemInfoSync();
|
||||||
|
if(sys.windowTop) vm.windowTop = sys.windowTop;
|
||||||
|
if(sys.windowBottom) vm.windowBottom = sys.windowBottom;
|
||||||
|
if(sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||||
|
if(sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||||
|
// 使down的bottomOffset生效
|
||||||
|
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||||
|
|
||||||
|
// 因为使用的是scrollview,这里需自定义scrollTo
|
||||||
|
vm.mescroll.resetScrollTo((y, t) => {
|
||||||
|
vm.scrollAnim = (t !== 0); // t为0,则不使用动画过渡
|
||||||
|
if(typeof y === 'string'){
|
||||||
|
// 小程序不支持slot里面的scroll-into-view, 统一使用计算的方式实现
|
||||||
|
vm.getClientInfo(function(rect){
|
||||||
|
let mescrollTop = rect.top // mescroll到顶部的距离
|
||||||
|
let selector;
|
||||||
|
if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
|
||||||
|
selector = '#'+y // 不带#和. 则默认为id选择器
|
||||||
|
}else{
|
||||||
|
selector = y
|
||||||
|
// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
|
||||||
|
if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
|
||||||
|
selector = y.split('>>>')[1].trim()
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
|
||||||
|
if (rect) {
|
||||||
|
let curY = vm.mescroll.getScrollTop()
|
||||||
|
let top = rect.top - mescrollTop
|
||||||
|
top += curY
|
||||||
|
if(!vm.isFixed) top -= vm.numTop
|
||||||
|
vm.scrollTop = curY;
|
||||||
|
vm.$nextTick(function() {
|
||||||
|
vm.scrollTop = top
|
||||||
|
})
|
||||||
|
} else{
|
||||||
|
console.error(selector + ' does not exist');
|
||||||
|
}
|
||||||
|
}).exec()
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let curY = vm.mescroll.getScrollTop()
|
||||||
|
if (t === 0 || t === 300) { // 当t使用默认配置的300时,则使用系统自带的动画过渡
|
||||||
|
vm.scrollTop = curY;
|
||||||
|
vm.$nextTick(function() {
|
||||||
|
vm.scrollTop = y
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
vm.mescroll.getStep(curY, y, step => { // 此写法可支持配置t
|
||||||
|
vm.scrollTop = step
|
||||||
|
}, t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||||
|
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
|
||||||
|
vm.mescroll.optUp.toTop.safearea = vm.safearea;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局配置监听
|
||||||
|
uni.$on("setMescrollGlobalOption", options=>{
|
||||||
|
if(!options) return;
|
||||||
|
let i18nType = options.i18n ? options.i18n.type : null
|
||||||
|
if(i18nType && vm.mescroll.i18n.type != i18nType){
|
||||||
|
vm.mescroll.i18n.type = i18nType
|
||||||
|
mescrollI18n.setType(i18nType)
|
||||||
|
MeScroll.extend(options, vm.mescroll.i18n[i18nType])
|
||||||
|
}
|
||||||
|
if(options.down){
|
||||||
|
let down = MeScroll.extend({}, options.down)
|
||||||
|
vm.mescroll.optDown = MeScroll.extend(down, vm.mescroll.optDown)
|
||||||
|
}
|
||||||
|
if(options.up){
|
||||||
|
let up = MeScroll.extend({}, options.up)
|
||||||
|
vm.mescroll.optUp = MeScroll.extend(up, vm.mescroll.optUp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 设置容器的高度
|
||||||
|
this.setClientHeight()
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
// 注销全局配置监听
|
||||||
|
uni.$off("setMescrollGlobalOption")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "../../mescroll-uni/mescroll-uni.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-down.css";
|
||||||
|
@import "../../mescroll-uni/components/mescroll-up.css";
|
||||||
|
@import "./components/mescroll-down.css";
|
||||||
|
@import "./components/mescroll-up.css";
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
<!--空布局:
|
||||||
|
遵循easycom规范, 可作为独立的组件, 不使用mescroll的页面也能使用:
|
||||||
|
<mescroll-empty v-if="isShowEmpty" :option="optEmpty" @emptyclick="emptyClick"></mescroll-empty>
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<view class="mescroll-empty" :class="{ 'empty-fixed': option.fixed }" :style="{ 'z-index': option.zIndex, top: option.top }">
|
||||||
|
<view> <image v-if="icon" class="empty-icon" :src="icon" mode="widthFix" /> </view>
|
||||||
|
<view v-if="tip" class="empty-tip">{{ tip }}</view>
|
||||||
|
<view v-if="btnText" class="empty-btn" @click="emptyClick">{{ btnText }}</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 引入全局配置
|
||||||
|
import GlobalOption from '../mescroll-uni/mescroll-uni-option.js';
|
||||||
|
// 引入国际化工具类
|
||||||
|
import mescrollI18n from '../mescroll-uni/mescroll-i18n.js';
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// empty的配置项: 默认为GlobalOption.up.empty
|
||||||
|
option: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 使用computed获取配置,用于支持option的动态配置
|
||||||
|
computed: {
|
||||||
|
// 图标
|
||||||
|
icon() {
|
||||||
|
if (this.option.icon != null) { // 此处不使用短路求值, 用于支持传空串不显示图标
|
||||||
|
return this.option.icon
|
||||||
|
} else{
|
||||||
|
let i18nType = mescrollI18n.getType() // 国际化配置
|
||||||
|
if (this.option.i18n) {
|
||||||
|
return this.option.i18n[i18nType].icon
|
||||||
|
} else{
|
||||||
|
return GlobalOption.i18n[i18nType].up.empty.icon || GlobalOption.up.empty.icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 文本提示
|
||||||
|
tip() {
|
||||||
|
if (this.option.tip != null) { // 支持传空串不显示文本提示
|
||||||
|
return this.option.tip
|
||||||
|
} else{
|
||||||
|
let i18nType = mescrollI18n.getType() // 国际化配置
|
||||||
|
if (this.option.i18n) {
|
||||||
|
return this.option.i18n[i18nType].tip
|
||||||
|
} else{
|
||||||
|
return GlobalOption.i18n[i18nType].up.empty.tip || GlobalOption.up.empty.tip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 按钮文本
|
||||||
|
btnText() {
|
||||||
|
if (this.option.i18n) {
|
||||||
|
let i18nType = mescrollI18n.getType() // 国际化配置
|
||||||
|
return this.option.i18n[i18nType].btnText
|
||||||
|
} else{
|
||||||
|
return this.option.btnText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击按钮
|
||||||
|
emptyClick() {
|
||||||
|
this.$emit('emptyclick');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* 无任何数据的空布局 */
|
||||||
|
.mescroll-empty {
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
padding: 100rpx 50rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mescroll-empty.empty-fixed {
|
||||||
|
z-index: 99;
|
||||||
|
position: absolute; /*transform会使fixed失效,最终会降级为absolute */
|
||||||
|
top: 100rpx;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mescroll-empty .empty-icon {
|
||||||
|
width: 280rpx;
|
||||||
|
height: 280rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mescroll-empty .empty-tip {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mescroll-empty .empty-btn {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
min-width: 200rpx;
|
||||||
|
padding: 18rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border: 1rpx solid #e04b28;
|
||||||
|
border-radius: 60rpx;
|
||||||
|
color: #e04b28;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mescroll-empty .empty-btn:active {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* 下拉刷新区域 */
|
||||||
|
.mescroll-downwarp {
|
||||||
|
position: absolute;
|
||||||
|
top: -100%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 下拉刷新--内容区,定位于区域底部 */
|
||||||
|
.mescroll-downwarp .downwarp-content {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 60rpx;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 下拉刷新--提示文本 */
|
||||||
|
.mescroll-downwarp .downwarp-tip {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
/* color: gray; 已在style设置color,此处删去*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 下拉刷新--旋转进度条 */
|
||||||
|
.mescroll-downwarp .downwarp-progress {
|
||||||
|
display: inline-block;
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid gray;
|
||||||
|
border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 旋转动画 */
|
||||||
|
.mescroll-downwarp .mescroll-rotate {
|
||||||
|
animation: mescrollDownRotate 0.6s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes mescrollDownRotate {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!-- 下拉刷新区域 -->
|
||||||
|
<template>
|
||||||
|
<view v-if="mOption.use" class="mescroll-downwarp" :style="{'background-color':mOption.bgColor,'color':mOption.textColor}">
|
||||||
|
<view class="downwarp-content">
|
||||||
|
<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mOption.textColor, 'transform':downRotate}"></view>
|
||||||
|
<view class="downwarp-tip">{{downText}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
option: Object , // down的配置项
|
||||||
|
type: Number, // 下拉状态(inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
|
||||||
|
rate: Number // 下拉比率 (inOffset: rate<1; outOffset: rate>=1)
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||||
|
mOption(){
|
||||||
|
return this.option || {}
|
||||||
|
},
|
||||||
|
// 是否在加载中
|
||||||
|
isDownLoading(){
|
||||||
|
return this.type === 3
|
||||||
|
},
|
||||||
|
// 旋转的角度
|
||||||
|
downRotate(){
|
||||||
|
return 'rotate(' + 360 * this.rate + 'deg)'
|
||||||
|
},
|
||||||
|
// 文本提示
|
||||||
|
downText(){
|
||||||
|
switch (this.type){
|
||||||
|
case 1: return this.mOption.textInOffset;
|
||||||
|
case 2: return this.mOption.textOutOffset;
|
||||||
|
case 3: return this.mOption.textLoading;
|
||||||
|
case 4: return this.mOption.textLoading;
|
||||||
|
default: return this.mOption.textInOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@import "./mescroll-down.css";
|
||||||
|
</style>
|
||||||