<template>
<view>
<view class="noActivityBox" v-if="showNoActivity">
<image src="/static/images/ve-match/noActivity.png" mode="" class="noActivityImg"></image>
<view class="activityText" v-if="showEndText">
<view>活动已结束</view>
<view style="margin-top: 20rpx;">感谢您的关注</view>
</view>
<view class="activityText" v-if="showStartText">{{activityText}}</view>
</view>
<view class="c-header" v-if="!showNoActivity">
<view style="width: 750rpx;height: 344rpx;"></view>
<view class="h-grid">
<view class="g-num">
<view class="n-item">
<view class="l-text1" v-if="Number(amount) > 0" style="color: #f65252;">
<text v-if="Number(amount) > 999999.99" style="font-size: 40rpx;">+100<text style="font-size: 26rpx;">W+</text></text>
<text v-else>{{'+'+amount}}</text>
</view>
<view class="l-text1" v-else-if="Number(amount) < 0" style="color: #68ee49;">
<text v-if="Math.abs(Number(amount)) > 999999.99" style="font-size: 40rpx;">-100<text style="font-size: 26rpx;">W+</text></text>
<text v-else>{{amount}}</text>
</view>
<view class="l-text1" v-else>{{amount}}</view>
<view class="l-text2">盈亏资产</view>
</view>
<view class="n-line"></view>
<view class="n-item">
<view class="l-text1" v-if="Number(yibeiNum) > 9999.99">1<text style="font-size: 26rpx;">W+</text></view>
<view class="l-text1" v-else>{{yibeiNum}}</view>
<view class="l-text2">可兑换积分</view>
</view>
</view>
<view class="g-check">
<view class="c-left">兑换数量</view>
<view class="c-center">
<view class="c-box">
<view class="b-circle" @click="btnClick(1)">-</view>
<input type="number" v-model="num" @blur="inputBlur" @focus="inputFocus" @input="changePayNum" class="b-text" ref="ipt">
<view class="b-circle" @click="btnClick(2)">+</view>
</view>
</view>
<view class="c-right">积分</view>
</view>
</view>
<image src="../../static/images/ve-match/m-bg9.png" mode="" class="h-btn" @click="confirm" v-if="showExchangeImg"></image>
<image src="../../static/images/ve-match/m-bg10.png" mode="" class="h-btn" v-else></image>
</view>
<view class="c-content" v-if="!showNoActivity">
<view class="c-rule">
<view class="r-title">
<view class="t-thread"></view>
<view class="t-name">兑换规则</view>
</view>
<view class="r-conten">
{{exchangeRules}}
</view>
</view>
<view class="c-exchange">
<view class="e-title">
<view class="t-left">
<view class="t-thread"></view>
<view class="t-name">兑换明细</view>
</view>
<view class="t-right" v-if="Number(exchangedAmount) > 9999.99">
已兑换积分共计:1<text style="font-size: 24rpx;">W+</text>
</view>
<view class="t-right" v-else>
已兑换积分共计:{{ exchangedAmount === null || exchangedAmount === '' ? '0.00' : exchangedAmount }}
</view>
</view>
<view class="e-list">
<block v-if="exchangeList.length > 0">
<view class="e-item" v-for="(item,index) in exchangeList" :key="index">
<view class="i-left">
<view class="l-name">兑换积分</view>
<view class="l-time">{{item.createTime}}</view>
</view>
<view class="i-right">-{{item.exchangeAmountTitle}}</view>
</view>
<!-- uView LoadMore 加载更多组件 -->
<u-loadmore :status="loadStatus" style="padding-bottom: 20rpx;"></u-loadmore>
</block>
<view class="e-empty" v-else>
<image src="/static/images/empty.png" mode=""></image>
<text>暂无兑换记录哦~</text>
</view>
</view>
</view>
</view>
<!-- 回到列表顶部按钮 -->
<b-fab :defaultPost="'right'" :defaultY="100">
<view class="fab" :xGap="40" :bottomGap="40" @tap="scrollTopData">
<image src="/static/images/genius/go-back.png" class="scroll-top"
:class="{'show-img':scrollTopPage<200}"></image>
</view>
</b-fab>
</view>
</template>
<script>
import { getSession } from "@/util/storage";
import { hex_md5 } from "@/util/md5";
import { getVirtualCoinNumber, queryActivitySettings, queryConvertTime, queryExchangeRules, exchangeVirtualCoin, queryExchangeCoin} from "@/api/exchange.js"; // 后端接口
import { dateFormat } from "@/common/dateFormat.js";
export default {
data() {
return {
competitionId:'', // 活动id
page: 1,
limit: 5,
amount:0,//盈亏资产金额
exchangeAsset:0,//可兑换资产额度
exchangedAmount:0,//已兑换额度
exchangeList:[],//兑换列表
yibeiNum: '0' ,//可兑换积分数量
num: '0',
loadStatus: 'more',
activityText: '', // 当前时间小于活动开始时间展示文本
showStartText: false, // 是否显示当前时间小于活动开始时间展示文本
activityStartTime: '', // 兑换活动开始时间
activityEndTime: '', // 兑换活动结束时间
showNoActivity: false, // 是否显示活动结束页面
showEndText: false, // 是否显示活动结束文本
exchangeRules: '', // 活动兑换规则文本
isBottom: !1, //定义变量为false
scrollTopPage: 0, // 距离顶部距离
showExchangeImg: false, // 是否显示兑换图片
};
},
watch:{
num(val) {
if (Number(val) > Number(this.yibeiNum)) {
this.$nextTick(() => {
this.num = this.yibeiNum
this.showExchangeImg = true
})
} else if (Number(val) < 0 || Number(val) == 0.01) {
this.$nextTick(() => {
this.num = 0.01
this.showExchangeImg = true
})
} else if (Number(val) > 0.01 && Number(val) < Number(this.yibeiNum)) {
this.showExchangeImg = true
} else if (val == '' || Number(val) == 0) {
this.showExchangeImg = false
}
}
},
onLoad(options){
window.yibeiPayCallback = (data) => {
let t = (new Date()).getTime();
let s = hex_md5(data + getSession("token") + this.num + this.competitionId + t);
// 调兑换的接口
this.updataYibei(t, s)
}
this.competitionId = options.id
this.getVirtualCoinNumber()
this.getActivitySettings()
this.getConvertTime()
this.getExchangeRules()
},
// 实时获取滚动条的位置
onPageScroll(res) {
this.scrollTopPage = res.scrollTop
},
methods:{
// 失去焦点时输入框积分赋值
inputBlur() {
if (Number(this.num) == 0) {
this.num = '0.01'
} else if (Number(this.num) >= Number(this.yibeiNum)) {
this.num = Number(this.yibeiNum)
} else {
let inputNum = Number(this.num.toString().match(/^\d+(?:\.\d{0,2})?/)[0]).toString().replace(/^0+\./g,'0.') // 只能输入数字
if (Number(inputNum) == 0) {
this.num = '0.01'
} else {
this.num = Number(inputNum).toFixed(2)
}
}
this.showExchangeImg = true
},
// 聚焦时输入框积分赋值
inputFocus() {
this.num = Number(this.num)
},
// 积分加减
btnClick(type) {
if(type == 1) { //减
if (Number(this.num) > 0.01) {
this.getExchangeCoin(type)
}
} else { //加
if(Number(this.num) < Number(this.yibeiNum)) {
this.getExchangeCoin(type)
}
}
},
//回到列表顶部
scrollTopData() {
uni.pageScrollTo({
selector: ".c-header",
scrollTop: 0
})
},
// 改变积分兑换数量
changePayNum(e) {
this.num = e.detail.value
},
// 可兑换积分计算
getExchangeCoin(type) {
let params = {
value: Number(this.num), // 原始值
isAdd: type == 1 ? false : true, // 是否相加,true为相加
changeNumber: 1, // 要加减的目标值
point: 2 // 限定的小数位
}
queryExchangeCoin(params).then(res => {
this.num = res.resultData
})
},
// 获取积分兑换活动开始和结束时间
getActivitySettings() {
queryActivitySettings().then(res => {
this.activityStartTime = res.data.startTime
this.activityEndTime = res.data.endTime
let nowTime = dateFormat(Date.now(), "yyyy-MM-dd hh:mm:ss")
let oDate1 = new Date(nowTime)
let oDate2 = new Date(this.activityStartTime)
let oDate3 = new Date(this.activityEndTime)
if(oDate1.getTime() < oDate2.getTime()){
this.showNoActivity = true
this.showEndText = false
this.showStartText = true
}
if(oDate1.getTime() > oDate3.getTime()){
this.showNoActivity = true
this.showEndText = true
this.showStartText = false
}
})
},
// 获取积分兑换时间
getConvertTime() {
queryConvertTime().then(res => {
this.convertTime = res.data.exchangeTime // 积分兑换时间
let nowTime1 = dateFormat(Date.now(), "yyyy-MM-dd hh:mm:ss")
let oDate1 = new Date(nowTime1)
let oDate2 = new Date(this.activityStartTime)
let oDate3 = new Date(this.activityEndTime)
if(oDate1.getTime() > oDate2.getTime() && oDate1.getTime() < oDate3.getTime()){
this.showNoActivity = false
}
})
},
// 获取积分兑换规则
getExchangeRules() {
let params = {
activeId: this.competitionId
}
queryExchangeRules(params).then(res => {
this.activityText = res.data.defaultPrompt
this.exchangeRules = res.data.rules
})
},
// 获取页面盈亏资产等数据
async getVirtualCoinNumber() {
let res = await getVirtualCoinNumber({
competitionId:this.competitionId,
pageIndex:this.page,
pageSize:this.limit,
token: getSession("token")
})
this.amount = res.resultData.amountTitle
this.exchangeAsset = res.resultData.exchangeAsset
this.exchangedAmount = res.resultData.totalExchangedBalance
this.yibeiNum = Number(res.resultData.accountBalanceTitle) < 0 ? '0.00' : res.resultData.accountBalanceTitle
this.num = this.yibeiNum
if (Number(this.yibeiNum) > 0) {
this.showExchangeImg = true
} else {
this.showExchangeImg = false
}
let tempList = []
tempList = res.resultData.data //定义第1页赋值
if (!tempList || tempList.length == 0) { // 无数据时
this.exchangeList = []
} else { //有数据时
this.isBottom = !1 //定义变量为false
this.exchangeList = this.exchangeList.concat(...tempList)
}
// 数据全部加载完成(停止下拉加载)
if (this.exchangeList.length >= res.total) {
this.loadStatus = 'noMore'
} else {
this.loadStatus = 'loading'
}
},
// 点击确定兑换
confirm() {
// 调取原生的积分支付界面
let isIOS = getSession("isIOS");
let isAndroid = getSession("isAndroid");
let obj = {
name: "积分兑换",
yibei: this.num
};
if (isAndroid) {
window.ytyJsApi.onYibeiPay(JSON.stringify(obj));
}
if (isIOS) {
window.webkit.messageHandlers.onYibeiPay.postMessage(
JSON.stringify(obj)
);
}
},
// 兑换回调
async updataYibei(t,s) {
let res = await exchangeVirtualCoin({
competitionId: this.competitionId,
changeMoney: this.num,
t:t,
s:s,
matchName: '积分兑换',
pageSize: 10,
token: getSession("token")
})
if(res.status == 1) {
uni.showToast({
title:'兑换成功',
icon:'none'
})
this.exchangeList = []
this.isBottom = !1
this.page = 1
this.getVirtualCoinNumber()
}else {
uni.showToast({
title: res.msg,
icon: 'none'
})
}
}
},
onReachBottom() {
// 判断数据是否全部加载完
if (!this.isBottom && this.loadStatus === 'loading') {
this.isBottom = !0 //定义变量为true
this.page += 1
this.getVirtualCoinNumber()
} else {
this.loadStatus = 'noMore'
}
}
}
</script>
<style lang="less" scoped>
.scroll-top {
position: relative;
width: 82rpx;
height: 82rpx;
border-radius: 50%;
opacity: 1;
transition: opacity .5s;
-webkit-transition: opacity .5s;
bottom: 60rpx;
}
.show-img {
opacity: 0;
}
.noActivityBox {
width: 100%;
height: calc(100vh - 88rpx);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.noActivityImg {
width: 360rpx;
height: 274rpx;
display: block;
background-size: 100% 100%;
}
.activityText {
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: #999999;
line-height: 40rpx;
margin-top: 32rpx;
white-space: pre-wrap;
text-align: center;
}
}
view {
line-height: 1;
}
.e-empty {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 750rpx;
image {
width: 320rpx;
height: 268rpx;
}
text {
font-size: 24rpx;
font-family: PingFang SC;
font-weight: 500;
color: #999999;
margin-top: 22rpx;
}
}
.c-content {
width: 750rpx;
background: #EEF3FD;
border-radius: 20rpx 20rpx 0px 0px;
padding: 28rpx 20rpx;
margin-top: -26rpx;
.c-rule{
width: 710rpx;
box-sizing: border-box;
padding: 32rpx;
margin-bottom: 20rpx;
background-color:#fff;
border-radius: 10rpx;
.r-title{
margin-bottom: 20rpx;
display: flex;
align-items: center;
.t-thread{
width: 4rpx;
height: 22rpx;
background: #6C8FF8;
}
.t-name{
margin-left: 15rpx;
font-size: 30rpx;
font-weight: bold;
color: #333333;
}
}
.r-conten{
font-size: 28rpx;
line-height: 48rpx;
font-weight: 500;
color: #666666;
white-space: pre-wrap;
}
}
.c-exchange{
box-sizing: border-box;
padding: 0 32rpx;
background-color:#fff;
border-radius: 10rpx;
.e-title{
padding: 32rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1rpx solid #EAEBEE;
.t-left{
display: flex;
align-items: center;
.t-thread{
width: 4rpx;
height: 22rpx;
background: #6C8FF8;
}
.t-name{
margin-left: 15rpx;
font-size: 30rpx;
font-weight: bold;
color: #333333;
}
}
.t-right{
font-size: 24rpx;
color: #6C8FF8;
}
}
.e-list {
width: 100%;
min-height: 750rpx;
}
.e-item{
display: flex;
align-items: center;
justify-content: space-between;
height: 140rpx;
border-bottom: 1rpx solid #EAEBEE;
.i-left{
display: flex;
flex-direction: column;
.l-name{
font-size: 28rpx;
color: #333333;
}
.l-time{
font-size: 24rpx;
color: #999999;
margin-top: 16rpx;
}
}
.i-right{
font-size: 28rpx;
font-weight: bold;
color: #EA3F49;
}
}
}
}
.c-header {
background: url("/static/images/ve-match/m-bg6.png") no-repeat;
background-size: 100% 100%;
width: 750rpx;
height: 974rpx;
.h-grid {
background: url("/static/images/ve-match/m-bg8.png") no-repeat;
background-size: 100% 100%;
width: 700rpx;
height: 444rpx;
margin: 0 auto;
overflow: hidden;
.g-tip {
display: flex;
align-items: center;
justify-content: center;
width: 370rpx;
height: 50rpx;
background: #3325E4;
border-radius: 25rpx;
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: #C5C0FF;
margin: 38rpx auto 0;
}
.g-check {
display: flex;
align-items: center;
margin-top: 76rpx;
height: 70rpx;
.c-left {
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
margin-left: 56rpx;
}
.c-center {
display: flex;
align-items: center;
margin-left: 18rpx;
font-size: 26rpx;
font-weight: 500;
color: #FFFFFF;
.c-box {
display: flex;
align-items: center;
justify-content: space-between;
width: 400rpx;
height: 70rpx;
background: #291ECC;
border-radius: 35rpx;
padding: 0 4rpx;
font-size: 40rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
.b-circle {
display: flex;
// align-items: center;
justify-content: center;
width: 60rpx;
height: 60rpx;
background: #4738EE;
border-radius: 50%;
font-size: 50rpx;
}
.b-text {
flex: 1;
text-align: center;
}
}
}
.c-right {
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
margin-left: 19rpx;
}
}
.g-num {
display: flex;
width: 586rpx;
height: 174rpx;
margin: 60rpx auto 0;
.n-item {
flex:1;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.l-text1 {
font-size: 40rpx;
font-family: PingFang SC;
font-weight: bold;
color: #FFFFFF;
}
.l-text2 {
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
margin-top: 18rpx;
}
}
}
}
.h-btn {
width: 698rpx;
height: 148rpx;
margin: -36rpx auto 0;
display: block;
}
}
</style>
置顶组件:
<template>
<view class="mo-fab"
:class="isShow ? '' : 'hideView'"
:animation="animationData"
@touchstart="drag_start"
@touchmove.stop.prevent="drag_move"
@touchend.stop="drag_end"
@touchcancel.stop="drag_end"
>
<view>
<slot
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO || MP-BAIDU -->
v-if="zScopedSlots.default||zSlots.default"
<!-- #endif -->
<!-- #ifndef MP-WEIXIN || MP-QQ || MP-TOUTIAO || MP-BAIDU -->
v-if="$scopedSlots.default||$slots.default"
<!-- #endif -->
></slot>
<template v-else>
<view class="mo-fab--wrap">
<slot
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO || MP-BAIDU -->
v-if="zScopedSlots.content||zSlots.content"
<!-- #endif -->
<!-- #ifndef MP-WEIXIN || MP-QQ || MP-TOUTIAO || MP-BAIDU -->
v-if="$scopedSlots.content||$slots.content"
<!-- #endif -->
name="content"
></slot>
<text v-else>示例</text>
</view>
</template>
</view>
</view>
</template>
<script>
/**
* 一个悬浮拖拽框
使用示例1:<moFab />
使用示例2:<moFab>内容</moFab>
使用示例3:<moFab><template #content>示例3</template></moFab>
*
*/
export default {
name: 'moFab',
props: {
type: { // 悬停类型 left-right || left || right || none
type: String,
default: 'left-right'
},
defaultPost: { // 初始化位置 left || right
type: String,
default: 'left'
},
defaultY: { // 初始化位置距离底部的距离
type: Number,
default: 200
},
xGap: { // 距离左右两边最小间距
type: Number,
default: 35
},
topGap: { // 距离顶部最小间距
type: Number,
default: 200
},
bottomGap: { // 距离底部最小间距
type: Number,
default: 80
},
defer: { // 是否开启惯性位移
type: Boolean,
default: true
},
deferVal: { // 惯性位移量
type: Number,
default: 150
},
},
data() {
return {
fabWidth: 50,
fabHeight: 50,
start: [0,0],
move: [0,0],
pages: [0,0],
animationData: {},
times: [0,0],
isShow: false,
}
},
computed:{
zScopedSlots() {
return this.$scopedSlots;
},
zSlots() {
return this.$slots;
}
},
mounted() {
this.initmove()
},
methods: {
getPageHeight(){
// px转换到rpx的比例
const { windowWidth, windowHeight } = uni.getSystemInfoSync();
const pxToRpxScale = 750 / windowWidth;
this.pages = [windowWidth, windowHeight]
return { pxToRpxScale }
},
initmove(){
const { pxToRpxScale } = this.getPageHeight()
const defaultY = this.defaultY / pxToRpxScale
const bottomGap = this.bottomGap / pxToRpxScale
const query = uni.createSelectorQuery().in(this);
query.select('.mo-fab').boundingClientRect(res=>{
if(!res) return
this.fabWidth = res.width
this.fabHeight = res.height
let moveX = this.pages[0] - this.fabWidth - this.xGap / pxToRpxScale
let moveY = this.pages[1] - this.fabHeight - (bottomGap > defaultY ? bottomGap : defaultY )
if(this.defaultPost == 'left'){
moveX = this.xGap / pxToRpxScale
}
const dir = moveX > (this.pages[0] - this.fabWidth) / 2 ? -1 : 1
this.move = [moveX,moveY]
this.setmove({
duration: 0,
timingFunction: 'linear',
x: this.move[0],
y: this.move[1]
})
setTimeout(() => {
this.isShow = true;
}, 500)
this.$emit('dragInit',{dir, grid: this.move})
}).exec();
},
setmove(ops){
const { duration, timingFunction, x, y } = Object.assign({
duration: 0,
timingFunction: 'linear',
x: 0,
y: 0
}, ops)
let animation = uni.createAnimation({
duration,
timingFunction,
delay: 0,
})
animation.translate(x,y).step()
this.animation = animation
this.animationData = this.animation.export()
},
drag_start(event){
const touches = event.touches[0] || event.changedTouches[0]
this.start = [touches.clientX, touches.clientY ]
this.times[0] = event.timeStamp
this.$emit('dragstart',event)
},
drag_move(event){
const touches = event.touches[0] || event.changedTouches[0];
const moveX = this.move[0] - this.start[0] + touches.clientX
const moveY = this.move[1] - this.start[1] + touches.clientY
const dir =moveX > (this.pages[0] - this.fabWidth) / 2 ? -1 : 1
this.setmove({
duration: 0,
timingFunction: 'linear',
x: moveX,
y: moveY
})
this.$emit('dragmove',{...event, dir, grid: this.move})
},
drag_end(event){
const touches = event.touches[0] || event.changedTouches[0];
this.times[1] = event.timeStamp
const timeDiff = this.times.reduce((a,b)=>b-a, 0)
const { pxToRpxScale } = this.getPageHeight()
const xGap = this.xGap / pxToRpxScale
const topGap = this.topGap / pxToRpxScale
const bottomGap = this.bottomGap / pxToRpxScale
const endX = this.pages[0] - this.fabWidth - xGap
const endY = this.pages[1] - this.fabHeight - bottomGap
const offx = touches.clientX - this.start[0]
const offy = touches.clientY - this.start[1]
let moveX = this.move[0] + offx
let moveY = this.move[1] + offy
if(this.defer){
moveX = moveX + this.getEndPost(offx,timeDiff)
moveY = moveY + this.getEndPost(offy,timeDiff)
}
moveY = moveY < topGap ? topGap : (moveY > endY ? endY : moveY)
if(this.type == 'left'){
moveX = xGap
}
if(this.type == 'right'){
moveX = endX
}
if(this.type == 'left-right'){
moveX = moveX > (this.pages[0] - this.fabWidth) / 2 ? endX : xGap
}
if(this.type == 'none'){
moveX = moveX < xGap ? xGap : (moveX > endX ? endX : moveX)
}
const dir = moveX > (this.pages[0] - this.fabWidth) / 2 ? -1 : 1
this.move = [moveX, moveY]
this.setmove({
duration: 250,
timingFunction: 'ease-out',
x: this.move[0],
y: this.move[1]
})
this.$emit('dragend',{...event, dir, grid: this.move})
},
getEndPost(offset, timeDiff){
let g = 2 * offset / Math.pow(timeDiff, 2)
const abs = Math.abs(+ (g * 10).toFixed(4))
g = abs < 0.01 ? 0 : g
return g * Math.pow(this.deferVal, 2) / 2
}
}
}
</script>
<style lang="scss" scoped>
.mo-fab {
display: block;
position: fixed;
top: 0;
left: 0;
color: #000;
z-index: 998;
user-select: none;
&.hideView {
opacity: 0;
}
&--wrap{
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
height: 100rpx;
width: 100rpx;
color: #fff;
box-shadow: 0px 7rpx 18rpx 0px rgba(107, 14, 195, 0.38);
border: 4rpx solid rgba(250, 121, 255, 0.8);
background: linear-gradient(90deg, #CD56FF, #833AD6);
}
}
</style>
dateFormat.js文件方法:
/**
* [dateFormat 时间格式化]
* @param {[Number,String]} [timestamp=Date.now()] [需转化的时间戳或一个能格式化的时间字符串]
* @param {[String]} [format='yyyy-M-d'] [需转化的时间格式]
* yyyy年,月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q),两个字符表示按2位字符输入
* 举例:
* dateFormat(Date.now(), "yyyy-MM-dd hh:mm:ss") ==> 2017-04-25 16:06:06
* dateFormat(Date.now(), "yyyy-M-d h:m:s q") ==> 2017-4-25 16:6:6 2
* @return {[String]} [格式化时间字符串]
*/
export function dateFormat(timestamp = Date.now(), format = 'yyyy-M-d') {
return getFormatDate(getJsonDate(timestamp), format)
}
// 生成时间对象
export function getJsonDate(timestamp) {
let time = new Date(getCorrectTime(timestamp))
let jsonDate = {
y: time.getFullYear(), //年
M: time.getMonth() + 1, //月
d: time.getDate(), //日
h: time.getHours(), //时
m: time.getMinutes(), //分
s: time.getSeconds(), //秒
q: Math.floor((time.getMonth() + 3) / 3) //季度
}
return jsonDate
}
// 生成格式化时间字符串
export function getFormatDate(jsonDate, format) {
let dateStr = format.replace(/yyyy/g, jsonDate.y)
Object.keys(jsonDate).forEach(e => {
// 时间格式化操作
let double = e.repeat(2)
let num = jsonDate[e]
if (format.includes(double)) {
// 如果需要两位的格式化数据,则转换为两位数
dateStr = dateStr.replace(double, getTwoDigit(num))
} else {
dateStr = dateStr.replace(e, num)
}
})
return dateStr
}
// 数字如果为一位数,前面加0
function getTwoDigit(num) {
return Number(num) < 10
? `0${num}`
: num
}
// 对于传入时间数据的转换
function getCorrectTime(timestamp) {
if (isNaN(timestamp)) {
// ios日期格式兼容处理
timestamp = timestamp.toString().includes('-')
? (timestamp.replace(/-/g, '/')).slice(0,19)
: timestamp
} else {
timestamp = Number(timestamp)
}
return timestamp
}
storage.js文件getSession方法:
// add by jq
const process = {
env:{
PROJECT_DIR_NAME: 'product/VTS',
// 如果自动获取本地ip不正确,则设置为false
isAutoGetIp: true,
// 是否随机配置本地端口号
isRandPort: true,
// 是否启用mock模拟数据
isUseMock: false
}
}
// projectConfig中的当前项目路径(如activities/CreditMonthExam)
const PROJECT_DIR_NAME = process.env.PROJECT_DIR_NAME.replace('/', '_')
// sessionStorage获取
export function getSession(key) {
if(key == "searchArr"){
let arr = getObjectValue(sessionStorage.getItem(getMixKey(key)))
if(arr && arr.length > 0){
return arr;
} else {
//ios15 searchArr数组可能太大,存储失败
let codeList = getObjectValue(localStorage.getItem(getMixKey("searchStr")))
if(codeList && codeList.length>0){
let arr01 = [],
arr02 = [],
arr03 = [];
arr01 = codeList.split(';');
arr01.forEach(item => {
let obj = {};
arr02 = item.split(',');
obj.a = arr02[0];
obj.b = arr02[1];
obj.c = arr02[2];
obj.d = arr02[3];
obj.e = arr02[4];
obj.f = arr02[5];
obj.g = arr02[6];
obj.h = arr02[7];
obj.i = arr02[8];
arr03.push(obj);
});
return arr03;
} else {
return [];
}
}
}
return getObjectValue(sessionStorage.getItem(getMixKey(key)))
}
// 获取混合后key名
export function getMixKey(key) {
return `${PROJECT_DIR_NAME}__${key}`
}
// 返回正确格式数据(若存储的时候为json,则直接返回json对象,否则为字符串)
// valueType 0字符类型,1json类型
export function getObjectValue(value) {
// 防止value为null的出错情况
let {valueType, realValue} = JSON.parse(value) || {}
return realValue
}
md5.js文件方法:
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
/*
* These are the export functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
export function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
export function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
export function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
export function hex_hmac_md5(k, d)
{ return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
export function b64_hmac_md5(k, d)
{ return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
export function any_hmac_md5(k, d, e)
{ return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
/*
* Perform a simple self-test to see if the VM is working
*/
export function md5_vm_test()
{
return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of a raw string
*/
export function rstr_md5(s)
{
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
export function rstr_hmac_md5(key, data)
{
var bkey = rstr2binl(key);
if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
export function rstr2hex(input)
{
try { hexcase } catch(e) { hexcase=0; }
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var output = "";
var x;
for(var i = 0; i < input.length; i++)
{
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F)
+ hex_tab.charAt( x & 0x0F);
}
return output;
}
/*
* Convert a raw string to a base-64 string
*/
export function rstr2b64(input)
{
try { b64pad } catch(e) { b64pad=''; }
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var output = "";
var len = input.length;
for(var i = 0; i < len; i += 3)
{
var triplet = (input.charCodeAt(i) << 16)
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > input.length * 8) output += b64pad;
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
}
}
return output;
}
/*
* Convert a raw string to an arbitrary string encoding
*/
export function rstr2any(input, encoding)
{
var divisor = encoding.length;
var i, j, q, x, quotient;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
var dividend = Array(Math.ceil(input.length / 2));
for(i = 0; i < dividend.length; i++)
{
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
/*
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. All remainders are stored for later
* use.
*/
var full_length = Math.ceil(input.length * 8 /
(Math.log(encoding.length) / Math.log(2)));
var remainders = Array(full_length);
for(j = 0; j < full_length; j++)
{
quotient = Array();
x = 0;
for(i = 0; i < dividend.length; i++)
{
x = (x << 16) + dividend[i];
q = Math.floor(x / divisor);
x -= q * divisor;
if(quotient.length > 0 || q > 0)
quotient[quotient.length] = q;
}
remainders[j] = x;
dividend = quotient;
}
/* Convert the remainders to the output string */
var output = "";
for(i = remainders.length - 1; i >= 0; i--)
output += encoding.charAt(remainders[i]);
return output;
}
/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
export function str2rstr_utf8(input)
{
var output = "";
var i = -1;
var x, y;
while(++i < input.length)
{
/* Decode utf-16 surrogate pairs */
x = input.charCodeAt(i);
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
{
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
i++;
}
/* Encode output as utf-8 */
if(x <= 0x7F)
output += String.fromCharCode(x);
else if(x <= 0x7FF)
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
0x80 | ( x & 0x3F));
else if(x <= 0xFFFF)
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
else if(x <= 0x1FFFFF)
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
0x80 | ((x >>> 12) & 0x3F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
}
return output;
}
/*
* Encode a string as utf-16
*/
export function str2rstr_utf16le(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
(input.charCodeAt(i) >>> 8) & 0xFF);
return output;
}
export function str2rstr_utf16be(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
input.charCodeAt(i) & 0xFF);
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
export function rstr2binl(input)
{
var output = Array(input.length >> 2);
for(var i = 0; i < output.length; i++)
output[i] = 0;
for(var i = 0; i < input.length * 8; i += 8)
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
return output;
}
/*
* Convert an array of little-endian words to a string
*/
export function binl2rstr(input)
{
var output = "";
for(var i = 0; i < input.length * 32; i += 8)
output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
return output;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
export function binl_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These export functions implement the four basic operations the algorithm uses.
*/
export function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
export function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
export function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
export function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
export function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
export function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
export function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
样式仅供参考,所用到的部分图片: