Commit 1573eb57 by linmin

提交代码

parent 1f58acec
<script>
import Vue from 'vue'
import {
getInvitaCode
} from '@/config/api.js'
export default {
onLaunch: function() {
console.log('App Launch')
const IMG_BASE_URL = "https://huarenv1.oss-cn-beijing.aliyuncs.com/huaren_icon/"
getInvitaCode('', {
suc: (res) => {
Vue.prototype.invateCode = res.data.code
}
})
uni.getSystemInfo({
success: function(e) {
//屏幕高度
Vue.prototype.ScreenHeight = uni.getSystemInfoSync().screenHeight;
// #ifndef MP
Vue.prototype.StatusBar = e.statusBarHeight;
if (e.platform == 'android') {
Vue.prototype.CustomBar = e.statusBarHeight + 50;
} else {
Vue.prototype.CustomBar = e.statusBarHeight + 45;
};
// #endif
// #ifdef MP-WEIXIN
Vue.prototype.StatusBar = e.statusBarHeight;
let custom = wx.getMenuButtonBoundingClientRect();
Vue.prototype.Custom = custom;
Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
// #endif
// #ifdef MP-ALIPAY
Vue.prototype.StatusBar = e.statusBarHeight;
Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
// #endif
}
})
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
body {
background-color: #f1f1f1;
}
view {
box-sizing: border-box;
}
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
/*单行*/
.singline {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;/*要显示的行数*/
overflow: hidden;
}
/*选项卡 插件v-tab 主要设置它的位置top*/
.tabs {
position: fixed;
/* #ifdef H5 */
top: 44px;
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
left: 0;
display: flex;
align-items: center;
width: 100%;
height: 100rpx;
box-sizing: border-box;
background-color: #fff;
box-shadow: 0px 0px 10rpx rgba(0, 0, 0, 0.1);
border-radius: 0px 0px 10rpx 10rpx;
z-index: 3;
}
.container-tabs__list {
height: 100%;
}
.container-tabs__swiper {
height: 100%;
}
/*分页*/
.loading-more {
align-items: center;
justify-content: center;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
}
.loading-more-text {
font-size: 28rpx;
color: #999;
}
</style>
<style lang="less">
/*每个页面公共css */
@import url("./static/style/cx-style.less");
/*自定义状态栏高度*/
.status-bar {
height: var(--status-bar-height);
width: 100%;
background-color: white;
}
/* https://www.jianshu.com/p/93d7104be420 、
去除自带的边框
*/
button {
background-color: white;
}
button::after {
border: none;
border-radius: 0;
}
button.theme {
width: calc(100% - 70rpx);
margin: 50rpx 35rpx 0 35rpx;
height: 88rpx;
line-height: 88rpx;
color: white;
font-size: 30rpx;
background-color: #21D183;
border-radius: 88rpx;
}
button.theme[disabled] {
color: white;
background-color: #DCDCDC;
}
uni-button.theme::after {
border: none;
}
</style>
\ No newline at end of file
export function adaptor(ctx) {
return Object.assign(ctx, {
setStrokeStyle(val) {
ctx.strokeStyle = val;
},
setLineWidth(val) {
ctx.lineWidth = val;
},
setLineCap(val) {
ctx.lineCap = val;
},
setFillStyle(val) {
ctx.fillStyle = val;
},
setFontSize(val) {
ctx.font = String(val);
},
setGlobalAlpha(val) {
ctx.globalAlpha = val;
},
setLineJoin(val) {
ctx.lineJoin = val;
},
setTextAlign(val) {
ctx.textAlign = val;
},
setMiterLimit(val) {
ctx.miterLimit = val;
},
setShadow(offsetX, offsetY, blur, color) {
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blur;
ctx.shadowColor = color;
},
setTextBaseline(val) {
ctx.textBaseline = val;
},
createCircularGradient() {},
draw() {},
});
}
/* eslint-disable */
export const GD = {
isGradient(bg) {
if (bg && (bg.startsWith('linear') || bg.startsWith('radial'))) {
return true;
}
return false;
},
doGradient(bg, width, height, ctx) {
if (bg.startsWith('linear')) {
linearEffect(width, height, bg, ctx);
} else if (bg.startsWith('radial')) {
radialEffect(width, height, bg, ctx);
}
},
}
function analizeGrad(string) {
const colorPercents = string.substring(0, string.length - 1).split("%,");
const colors = [];
const percents = [];
for (let colorPercent of colorPercents) {
colors.push(colorPercent.substring(0, colorPercent.lastIndexOf(" ")).trim());
percents.push(colorPercent.substring(colorPercent.lastIndexOf(" "), colorPercent.length) / 100);
}
return {
colors: colors,
percents: percents
};
}
function radialEffect(width, height, bg, ctx) {
const colorPer = analizeGrad(bg.match(/radial-gradient\((.+)\)/)[1]);
const grd = ctx.createCircularGradient(0, 0, width < height ? height / 2 : width / 2);
for (let i = 0; i < colorPer.colors.length; i++) {
grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
}
ctx.setFillStyle(grd);
}
function analizeLinear(bg, width, height) {
const direction = bg.match(/([-]?\d{1,3})deg/);
const dir = direction && direction[1] ? parseFloat(direction[1]) : 0;
let coordinate;
switch (dir) {
case 0:
coordinate = [0, -height / 2, 0, height / 2];
break;
case 90:
coordinate = [width / 2, 0, -width / 2, 0];
break;
case -90:
coordinate = [-width / 2, 0, width / 2, 0];
break;
case 180:
coordinate = [0, height / 2, 0, -height / 2];
break;
case -180:
coordinate = [0, -height / 2, 0, height / 2];
break;
default:
let x1 = 0;
let y1 = 0;
let x2 = 0;
let y2 = 0;
if (direction[1] > 0 && direction[1] < 90) {
x1 = (width / 2) - ((width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
} else if (direction[1] > -180 && direction[1] < -90) {
x1 = -(width / 2) + ((width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
} else if (direction[1] > 90 && direction[1] < 180) {
x1 = (width / 2) + (-(width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
} else {
x1 = -(width / 2) - (-(width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 *
(90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
}
coordinate = [x1, y1, x2, y2];
break;
}
return coordinate;
}
function linearEffect(width, height, bg, ctx) {
const param = analizeLinear(bg, width, height);
const grd = ctx.createLinearGradient(param[0], param[1], param[2], param[3]);
const content = bg.match(/linear-gradient\((.+)\)/)[1];
const colorPer = analizeGrad(content.substring(content.indexOf(',') + 1));
for (let i = 0; i < colorPer.colors.length; i++) {
grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
}
ctx.setFillStyle(grd);
}
<template>
<canvas v-if="use2dCanvas" :id="canvasId" type="2d" :style="style"></canvas>
<canvas v-else :canvas-id="canvasId" :style="style" :id="canvasId" :width="boardWidth * dpr" :height="boardHeight * dpr"></canvas>
</template>
<script>
import { toPx, base64ToPath, compareVersion} from './utils';
import { Draw } from './draw';
import { adaptor } from './canvas';
export default {
// version: '1.5.9.2',
name: 'l-painter',
props: {
board: Object,
fileType: {
type: String,
default: 'png'
},
width: [Number, String],
height: [Number, String],
pixelRatio: Number,
customStyle: String,
isRenderImage: Boolean,
isBase64ToPath: Boolean,
isH5PathToBase64: Boolean,
sleep: {
type: Number,
default: 1000/30
},
type: {
type: String,
default: '2d',
}
},
data() {
return {
// #ifndef MP-WEIXIN || MP-QQ
canvasId: `l-painter_${this._uid}`,
// #endif
// #ifdef MP-WEIXIN || MP-QQ
canvasId: `l-painter`,
// #endif
// #ifdef MP-WEIXIN
use2dCanvas: true,
// #endif
// #ifndef MP-WEIXIN
use2dCanvas: false,
// #endif
draw: null,
ctx: null
};
},
computed: {
newboard() {
return this.board && JSON.parse(JSON.stringify(this.board))
},
style() {
return `width:${this.boardWidth}px; height: ${this.boardHeight}px; ${this.customStyle}`;
},
dpr() {
return this.pixelRatio || uni.getSystemInfoSync().pixelRatio;
},
boardWidth() {
const { width = 200 } = this.board || {};
return toPx(this.width || width);
},
boardHeight() {
const { height = 200 } = this.board || {};
return toPx(this.height || height);
}
},
mounted() {
// #ifdef MP-WEIXIN
const {SDKVersion} = wx.getSystemInfoSync()
this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '2.9.2') >= 0;
// #endif
this.$watch('newboard', async (val, old) => {
if (JSON.stringify(val) === '{}' || !val) return;
const {width: w, height: h} = val || {};
const {width: ow, height: oh} = old || {};
if(w !== ow || h !== oh) {
this.inited = false;
}
this.render();
}, {
deep: true,
immediate: true,
})
},
methods: {
async render(args = {}, single = false) {
const ctx = await this.getContext()
const { use2dCanvas, boardWidth, boardHeight, board, canvas, isBase64ToPath, isH5PathToBase64, sleep } = this;
if (use2dCanvas && !canvas) {
return Promise.reject(new Error('render: fail canvas has not been created'));
}
if(!this.boundary) {
this.boundary = {
top: 0,
left: 0,
width: boardWidth,
height: boardHeight,
sleep
}
}
if(!single) {
ctx.clearRect(0, 0, boardWidth, boardHeight);
}
if(!this.draw) {
this.draw = new Draw(ctx, canvas, use2dCanvas, isH5PathToBase64, this.boundary);
}
if(JSON.stringify(args) != '{}' || board && JSON.stringify(board) != '{}') {
await this.draw.drawBoard(JSON.stringify(args) != '{}' ? args : board);
}
await new Promise(resolve => this.$nextTick(resolve))
if (!use2dCanvas && !single) {
await this.canvasDraw(ctx);
}
this.$emit('done')
if(this.isRenderImage && !single) {
this.canvasToTempFilePath()
.then(async res => {
if(/^data:image\/(\w+);base64/.test(res.tempFilePath) && isBase64ToPath) {
const img = await base64ToPath(res.tempFilePath)
this.$emit('success', img)
} else {
this.$emit('success', res.tempFilePath)
}
})
.catch(err => {
this.$emit('fail', err)
new Error(JSON.stringify(err))
console.error(111, JSON.stringify(err))
})
}
return Promise.resolve({ctx, draw: this.draw});
},
async custom(cb) {
const {ctx, draw} = await this.render({}, true)
ctx.save()
await cb(ctx, draw)
ctx.restore()
return Promise.resolve(true);
},
async single(args = {}) {
await this.render(args, true)
return Promise.resolve(true);
},
canvasDraw(flag = false) {
const {ctx} = this
return new Promise(resolve => {
ctx.draw(flag, () => {
resolve(true);
});
});
},
async getContext() {
if(this.ctx && this.inited) {
return Promise.resolve(this.ctx)
};
const { type, use2dCanvas, dpr, boardWidth, boardHeight } = this;
const _getContext = () => {
return new Promise(resolve => {
uni.createSelectorQuery()
.in(this)
.select('#' + this.canvasId)
.boundingClientRect()
.exec(res => {
if(res) {
const ctx = uni.createCanvasContext(this.canvasId, this);
if (!this.inited) {
this.inited = true;
this.use2dCanvas = false;
this.canvas = res
}
// #ifdef MP-ALIPAY
ctx.scale(dpr, dpr);
// #endif
this.ctx = ctx
resolve(ctx);
}
})
})
}
// #ifndef MP-WEIXIN
return _getContext()
// #endif
if(!use2dCanvas) {
return _getContext()
}
return new Promise(resolve => {
uni.createSelectorQuery()
.in(this)
.select('#l-painter')
.node()
.exec(res => {
const canvas = res[0].node;
if(!canvas) {
this.use2dCanvas = false;
return this.getContext()
}
const ctx = canvas.getContext(type);
if (!this.inited) {
this.inited = true;
canvas.width = boardWidth * dpr;
canvas.height = boardHeight * dpr;
this.use2dCanvas = true;
this.canvas = canvas
ctx.scale(dpr, dpr);
}
this.ctx = adaptor(ctx)
resolve(adaptor(ctx));
});
});
},
canvasToTempFilePath(args = {}) {
const {use2dCanvas, canvasId} = this
return new Promise((resolve, reject) => {
let { top = 0, left = 0, width, height } = this.boundary || this
let destWidth = width * this.dpr
let destHeight = height * this.dpr
// #ifdef MP-ALIPAY
width = width * this.dpr
height = height * this.dpr
// #endif
const copyArgs = {
x: left,
y: top,
width,
height,
destWidth,
destHeight,
canvasId,
fileType: args.fileType || this.fileType,
quality: args.quality || 1,
success: resolve,
fail: reject
}
if (use2dCanvas) {
delete copyArgs.canvasId
copyArgs.canvas = this.canvas
}
uni.canvasToTempFilePath(copyArgs, this)
})
}
}
};
</script>
<style></style>
// 请去下载覆盖:https://gitee.com/liangei/lime-painter/blob/master/qrcode.js
\ No newline at end of file
export function adaptor(ctx) {
return Object.assign(ctx, {
setStrokeStyle(val) {
ctx.strokeStyle = val;
},
setLineWidth(val) {
ctx.lineWidth = val;
},
setLineCap(val) {
ctx.lineCap = val;
},
setFillStyle(val) {
ctx.fillStyle = val;
},
setFontSize(val) {
ctx.font = String(val);
},
setGlobalAlpha(val) {
ctx.globalAlpha = val;
},
setLineJoin(val) {
ctx.lineJoin = val;
},
setTextAlign(val) {
ctx.textAlign = val;
},
setMiterLimit(val) {
ctx.miterLimit = val;
},
setShadow(offsetX, offsetY, blur, color) {
ctx.shadowOffsetX = offsetX;
ctx.shadowOffsetY = offsetY;
ctx.shadowBlur = blur;
ctx.shadowColor = color;
},
setTextBaseline(val) {
ctx.textBaseline = val;
},
createCircularGradient() {},
draw() {},
});
}
/* eslint-disable */
export const GD = {
isGradient(bg) {
if (bg && (bg.startsWith('linear') || bg.startsWith('radial'))) {
return true;
}
return false;
},
doGradient(bg, width, height, ctx) {
if (bg.startsWith('linear')) {
linearEffect(width, height, bg, ctx);
} else if (bg.startsWith('radial')) {
radialEffect(width, height, bg, ctx);
}
},
}
function analizeGrad(string) {
const colorPercents = string.substring(0, string.length - 1).split("%,");
const colors = [];
const percents = [];
for (let colorPercent of colorPercents) {
colors.push(colorPercent.substring(0, colorPercent.lastIndexOf(" ")).trim());
percents.push(colorPercent.substring(colorPercent.lastIndexOf(" "), colorPercent.length) / 100);
}
return {
colors: colors,
percents: percents
};
}
function radialEffect(width, height, bg, ctx) {
const colorPer = analizeGrad(bg.match(/radial-gradient\((.+)\)/)[1]);
const grd = ctx.createCircularGradient(0, 0, width < height ? height / 2 : width / 2);
for (let i = 0; i < colorPer.colors.length; i++) {
grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
}
ctx.setFillStyle(grd);
}
function analizeLinear(bg, width, height) {
const direction = bg.match(/([-]?\d{1,3})deg/);
const dir = direction && direction[1] ? parseFloat(direction[1]) : 0;
let coordinate;
switch (dir) {
case 0:
coordinate = [0, -height / 2, 0, height / 2];
break;
case 90:
coordinate = [width / 2, 0, -width / 2, 0];
break;
case -90:
coordinate = [-width / 2, 0, width / 2, 0];
break;
case 180:
coordinate = [0, height / 2, 0, -height / 2];
break;
case -180:
coordinate = [0, -height / 2, 0, height / 2];
break;
default:
let x1 = 0;
let y1 = 0;
let x2 = 0;
let y2 = 0;
if (direction[1] > 0 && direction[1] < 90) {
x1 = (width / 2) - ((width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
} else if (direction[1] > -180 && direction[1] < -90) {
x1 = -(width / 2) + ((width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
} else if (direction[1] > 90 && direction[1] < 180) {
x1 = (width / 2) + (-(width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
} else {
x1 = -(width / 2) - (-(width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 *
(90 - direction[1]) * Math.PI * 2 / 360) / 2;
y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
x2 = -x1;
y1 = -y2;
}
coordinate = [x1, y1, x2, y2];
break;
}
return coordinate;
}
function linearEffect(width, height, bg, ctx) {
const param = analizeLinear(bg, width, height);
const grd = ctx.createLinearGradient(param[0], param[1], param[2], param[3]);
const content = bg.match(/linear-gradient\((.+)\)/)[1];
const colorPer = analizeGrad(content.substring(content.indexOf(',') + 1));
for (let i = 0; i < colorPer.colors.length; i++) {
grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
}
ctx.setFillStyle(grd);
}
<template>
<canvas v-if="use2dCanvas" :id="canvasId" type="2d" :style="style"></canvas>
<canvas v-else :canvas-id="canvasId" :style="style" :id="canvasId" :width="boardWidth * dpr" :height="boardHeight * dpr"></canvas>
</template>
<script>
import { toPx, base64ToPath, compareVersion} from './utils';
import { Draw } from './draw';
import { adaptor } from './canvas';
export default {
// version: '1.5.9.2',
name: 'l-painter',
props: {
board: Object,
fileType: {
type: String,
default: 'png'
},
width: [Number, String],
height: [Number, String],
pixelRatio: Number,
customStyle: String,
isRenderImage: Boolean,
isBase64ToPath: Boolean,
isH5PathToBase64: Boolean,
sleep: {
type: Number,
default: 1000/30
},
type: {
type: String,
default: '2d',
}
},
data() {
return {
// #ifndef MP-WEIXIN || MP-QQ
canvasId: `l-painter_${this._uid}`,
// #endif
// #ifdef MP-WEIXIN || MP-QQ
canvasId: `l-painter`,
// #endif
// #ifdef MP-WEIXIN
use2dCanvas: true,
// #endif
// #ifndef MP-WEIXIN
use2dCanvas: false,
// #endif
draw: null,
ctx: null
};
},
computed: {
newboard() {
return this.board && JSON.parse(JSON.stringify(this.board))
},
style() {
return `width:${this.boardWidth}px; height: ${this.boardHeight}px; ${this.customStyle}`;
},
dpr() {
return this.pixelRatio || uni.getSystemInfoSync().pixelRatio;
},
boardWidth() {
const { width = 200 } = this.board || {};
return toPx(this.width || width);
},
boardHeight() {
const { height = 200 } = this.board || {};
return toPx(this.height || height);
}
},
mounted() {
// #ifdef MP-WEIXIN
const {SDKVersion} = wx.getSystemInfoSync()
this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '2.9.2') >= 0;
// #endif
this.$watch('newboard', async (val, old) => {
if (JSON.stringify(val) === '{}' || !val) return;
const {width: w, height: h} = val || {};
const {width: ow, height: oh} = old || {};
if(w !== ow || h !== oh) {
this.inited = false;
}
this.render();
}, {
deep: true,
immediate: true,
})
},
methods: {
async render(args = {}, single = false) {
const ctx = await this.getContext()
const { use2dCanvas, boardWidth, boardHeight, board, canvas, isBase64ToPath, isH5PathToBase64, sleep } = this;
if (use2dCanvas && !canvas) {
return Promise.reject(new Error('render: fail canvas has not been created'));
}
if(!this.boundary) {
this.boundary = {
top: 0,
left: 0,
width: boardWidth,
height: boardHeight,
sleep
}
}
if(!single) {
ctx.clearRect(0, 0, boardWidth, boardHeight);
}
if(!this.draw) {
this.draw = new Draw(ctx, canvas, use2dCanvas, isH5PathToBase64, this.boundary);
}
if(JSON.stringify(args) != '{}' || board && JSON.stringify(board) != '{}') {
await this.draw.drawBoard(JSON.stringify(args) != '{}' ? args : board);
}
await new Promise(resolve => this.$nextTick(resolve))
if (!use2dCanvas && !single) {
await this.canvasDraw(ctx);
}
this.$emit('done')
if(this.isRenderImage && !single) {
this.canvasToTempFilePath()
.then(async res => {
if(/^data:image\/(\w+);base64/.test(res.tempFilePath) && isBase64ToPath) {
const img = await base64ToPath(res.tempFilePath)
this.$emit('success', img)
} else {
this.$emit('success', res.tempFilePath)
}
})
.catch(err => {
this.$emit('fail', err)
new Error(JSON.stringify(err))
console.error(JSON.stringify(err))
})
}
return Promise.resolve({ctx, draw: this.draw});
},
async custom(cb) {
const {ctx, draw} = await this.render({}, true)
ctx.save()
await cb(ctx, draw)
ctx.restore()
return Promise.resolve(true);
},
async single(args = {}) {
await this.render(args, true)
return Promise.resolve(true);
},
canvasDraw(flag = false) {
const {ctx} = this
return new Promise(resolve => {
ctx.draw(flag, () => {
resolve(true);
});
});
},
async getContext() {
if(this.ctx && this.inited) {
return Promise.resolve(this.ctx)
};
const { type, use2dCanvas, dpr, boardWidth, boardHeight } = this;
const _getContext = () => {
return new Promise(resolve => {
uni.createSelectorQuery()
.in(this)
.select('#' + this.canvasId)
.boundingClientRect()
.exec(res => {
if(res) {
const ctx = uni.createCanvasContext(this.canvasId, this);
if (!this.inited) {
this.inited = true;
this.use2dCanvas = false;
this.canvas = res
}
// #ifdef MP-ALIPAY
ctx.scale(dpr, dpr);
// #endif
this.ctx = ctx
resolve(ctx);
}
})
})
}
// #ifndef MP-WEIXIN
return _getContext()
// #endif
if(!use2dCanvas) {
return _getContext()
}
return new Promise(resolve => {
uni.createSelectorQuery()
.in(this)
.select('#l-painter')
.node()
.exec(res => {
const canvas = res[0].node;
if(!canvas) {
this.use2dCanvas = false;
return this.getContext()
}
const ctx = canvas.getContext(type);
if (!this.inited) {
this.inited = true;
canvas.width = boardWidth * dpr;
canvas.height = boardHeight * dpr;
this.use2dCanvas = true;
this.canvas = canvas
ctx.scale(dpr, dpr);
}
this.ctx = adaptor(ctx)
resolve(adaptor(ctx));
});
});
},
canvasToTempFilePath(args = {}) {
const {use2dCanvas, canvasId} = this
return new Promise((resolve, reject) => {
let { top = 0, left = 0, width, height } = this.boundary || this
let destWidth = width * this.dpr
let destHeight = height * this.dpr
// #ifdef MP-ALIPAY
width = width * this.dpr
height = height * this.dpr
// #endif
const copyArgs = {
x: left,
y: top,
width,
height,
destWidth,
destHeight,
canvasId,
fileType: args.fileType || this.fileType,
quality: args.quality || 1,
success: resolve,
fail: reject
}
if (use2dCanvas) {
delete copyArgs.canvasId
copyArgs.canvas = this.canvas
}
uni.canvasToTempFilePath(copyArgs, this)
})
}
}
};
</script>
<style></style>
export default {
'contact': '\ue100',
'person': '\ue101',
'personadd': '\ue102',
'contact-filled': '\ue130',
'person-filled': '\ue131',
'personadd-filled': '\ue132',
'phone': '\ue200',
'email': '\ue201',
'chatbubble': '\ue202',
'chatboxes': '\ue203',
'phone-filled': '\ue230',
'email-filled': '\ue231',
'chatbubble-filled': '\ue232',
'chatboxes-filled': '\ue233',
'weibo': '\ue260',
'weixin': '\ue261',
'pengyouquan': '\ue262',
'chat': '\ue263',
'qq': '\ue264',
'videocam': '\ue300',
'camera': '\ue301',
'mic': '\ue302',
'location': '\ue303',
'mic-filled': '\ue332',
'speech': '\ue332',
'location-filled': '\ue333',
'micoff': '\ue360',
'image': '\ue363',
'map': '\ue364',
'compose': '\ue400',
'trash': '\ue401',
'upload': '\ue402',
'download': '\ue403',
'close': '\ue404',
'redo': '\ue405',
'undo': '\ue406',
'refresh': '\ue407',
'star': '\ue408',
'plus': '\ue409',
'minus': '\ue410',
'circle': '\ue411',
'checkbox': '\ue411',
'close-filled': '\ue434',
'clear': '\ue434',
'refresh-filled': '\ue437',
'star-filled': '\ue438',
'plus-filled': '\ue439',
'minus-filled': '\ue440',
'circle-filled': '\ue441',
'checkbox-filled': '\ue442',
'closeempty': '\ue460',
'refreshempty': '\ue461',
'reload': '\ue462',
'starhalf': '\ue463',
'spinner': '\ue464',
'spinner-cycle': '\ue465',
'search': '\ue466',
'plusempty': '\ue468',
'forward': '\ue470',
'back': '\ue471',
'left-nav': '\ue471',
'checkmarkempty': '\ue472',
'home': '\ue500',
'navigate': '\ue501',
'gear': '\ue502',
'paperplane': '\ue503',
'info': '\ue504',
'help': '\ue505',
'locked': '\ue506',
'more': '\ue507',
'flag': '\ue508',
'home-filled': '\ue530',
'gear-filled': '\ue532',
'info-filled': '\ue534',
'help-filled': '\ue535',
'more-filled': '\ue537',
'settings': '\ue560',
'list': '\ue562',
'bars': '\ue563',
'loop': '\ue565',
'paperclip': '\ue567',
'eye': '\ue568',
'arrowup': '\ue580',
'arrowdown': '\ue581',
'arrowleft': '\ue582',
'arrowright': '\ue583',
'arrowthinup': '\ue584',
'arrowthindown': '\ue585',
'arrowthinleft': '\ue586',
'arrowthinright': '\ue587',
'pulldown': '\ue588',
'closefill': '\ue589',
'sound': '\ue590',
'scan': '\ue612'
}
<template>
<view class="uni-navbar">
<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }"
class="uni-navbar__content">
<uni-status-bar v-if="statusBar" />
<view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="leftIcon.length">
<uni-icons :color="color" :type="leftIcon" size="24" />
</view>
<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view"
v-if="leftText.length">
<text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
</view>
<slot name="left" />
</view>
<view class="uni-navbar__header-container uni-navbar__content_view">
<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
<text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
</view>
<!-- 标题插槽 -->
<slot />
</view>
<view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="rightIcon.length">
<uni-icons :color="color" :type="rightIcon" size="24" />
</view>
<!-- 优先显示图标 -->
<view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
<text class="uni-nav-bar-right-text">{{ rightText }}</text>
</view>
<slot name="right" />
</view>
</view>
</view>
<view class="uni-navbar__placeholder" v-if="fixed">
<uni-status-bar v-if="statusBar" />
<view class="uni-navbar__placeholder-view" />
</view>
</view>
</template>
<script>
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
import uniIcons from "../uni-icons/uni-icons.vue";
export default {
name: "UniNavBar",
components: {
uniStatusBar,
uniIcons
},
props: {
title: {
type: String,
default: ""
},
leftText: {
type: String,
default: ""
},
rightText: {
type: String,
default: ""
},
leftIcon: {
type: String,
default: ""
},
rightIcon: {
type: String,
default: ""
},
fixed: {
type: [Boolean, String],
default: false
},
color: {
type: String,
default: "#000000"
},
backgroundColor: {
type: String,
default: "#FFFFFF"
},
statusBar: {
type: [Boolean, String],
default: false
},
shadow: {
type: [String, Boolean],
default: false
},
border: {
type: [String, Boolean],
default: true
}
},
mounted() {
if(uni.report && this.title !== '') {
uni.report('title', this.title)
}
},
methods: {
onClickLeft() {
this.$emit("clickLeft");
},
onClickRight() {
this.$emit("clickRight");
}
}
};
</script>
<style lang="scss" scoped>
$nav-height: 44px;
.uni-nav-bar-text {
/* #ifdef APP-PLUS */
font-size: 34rpx;
/* #endif */
/* #ifndef APP-PLUS */
font-size: $uni-font-size-lg;
/* #endif */
}
.uni-nav-bar-right-text {
font-size: $uni-font-size-base;
}
.uni-navbar {
width: 750rpx;
}
.uni-navbar__content {
position: relative;
width: 750rpx;
background-color: $uni-bg-color;
overflow: hidden;
}
.uni-navbar__content_view {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
flex-direction: row;
// background-color: #FFFFFF;
}
.uni-navbar__header {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
width: 750rpx;
height: $nav-height;
line-height: $nav-height;
font-size: 16px;
// background-color: #ffffff;
}
.uni-navbar__header-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-wrap: nowrap;
width: 120rpx;
padding: 0 6px;
justify-content: center;
align-items: center;
}
.uni-navbar__header-btns-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
justify-content: flex-start;
}
.uni-navbar__header-btns-right {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
padding-right: 30rpx;
justify-content: flex-end;
}
.uni-navbar__header-container {
flex: 1;
}
.uni-navbar__header-container-inner {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
align-items: center;
justify-content: center;
font-size: $uni-font-size-base;
}
.uni-navbar__placeholder-view {
height: $nav-height;
}
.uni-navbar--fixed {
position: fixed;
z-index: 998;
}
.uni-navbar--shadow {
/* #ifndef APP-NVUE */
box-shadow: 0 1px 6px #ccc;
/* #endif */
}
.uni-navbar--border {
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: $uni-border-color;
}
</style>
export default {
created() {
if (this.type === 'message') {
// 不显示遮罩
this.maskShow = false
// 获取子组件对象
this.childrenMsg = null
}
},
methods: {
customOpen() {
if (this.childrenMsg) {
this.childrenMsg.open()
}
},
customClose() {
if (this.childrenMsg) {
this.childrenMsg.close()
}
}
}
}
import message from './message.js';
// 定义 type 类型:弹出类型:top/bottom/center
const config = {
// 顶部弹出
top:'top',
// 底部弹出
bottom:'bottom',
// 居中弹出
center:'center',
// 消息提示
message:'top',
// 对话框
dialog:'center',
// 分享
share:'bottom',
}
export default {
data(){
return {
config:config
}
},
mixins: [message],
}
<template>
<view class="uni-popup-select">
<view class="uni-select-title">
<text class="uni-select-title-text">选择支付方式</text>
<view class="close" @click="close">
<image src="/static/ic_black_close.png"></image>
</view>
</view>
<view class="uni-select-content">
<view class="row" @click="changePay(1)">
<view class="pay-type">
<image mode="aspectFill" src="/static/plays@3x.png"></image>
<label>支付宝支付</label>
</view>
<image class="choose" :src="payType == 1 ? '/static/Selecti.png' : '/static/ic_now.png'"></image>
</view>
<view class="row" @click="changePay(2)">
<view class="pay-type">
<image mode="aspectFill" src="/static/WChat@3x.png"></image>
<label>微信支付</label>
</view>
<image class="choose" :src="payType == 2 ? '/static/Selecti.png' : '/static/ic_now.png'"></image>
</view>
<view class="row" @click="changePay(3)" v-if="fromType == 1">
<view class="pay-type">
<image mode="aspectFill" src="/static/banlance.png"></image>
<label>余额支付</label>
</view>
<image class="choose" :src="payType == 3 ? '/static/Selecti.png' : '/static/ic_now.png'"></image>
</view>
<view class="row">
<button @click="sure">确认支付</button>
</view>
</view>
</view>
</template>
<script>
import util from '@/utils/util.js'
import {
balancePay,
createAliPayOrder,
wxPayCreateOrder
} from '@/utils/api.js'
export default {
props: {
payAmount: {
type: Number
},
combineOrderNo: {
type: String
},
fromType: { //1购买物品 2申请代理 3购买tz
type: Number
},
},
name: 'UniPopupPay',
inject: ['popup'],
data() {
return {
payType: 1
}
},
methods: {
// 修改支付方式
changePay(type) {
this.payType = type
},
// 关闭窗口
close() {
this.popup.close()
},
// 确认支付
sure() {
var params = {}
if (this.payType == 1) { //支付宝支付 需要传
params['amount'] = this.payAmount
params["tradeNo"] = this.combineOrderNo
params["type"] = this.fromType
}
if (this.payType == 2) { //微信支付 需要传
params['totalFee'] = this.payAmount
params["outTradeNo"] = this.combineOrderNo
params["type"] = this.fromType
}
if (this.payType == 3) { //余额支付 需要传
params['combineOrderNo'] = this.combineOrderNo
params['payAmount'] = this.payAmount
params["payType"] = this.payType
}
if (this.payType == 1) {
console.log('支付包参赛')
console.log(params)
// 支付宝支付
createAliPayOrder(params, {
suc: res => {
uni.requestPayment({
provider: 'alipay',
orderInfo: res.data,
success: res => {
this.$emit('ok')
this.close()
},
fail: err => {
util.printLog(err)
}
})
}
})
} else if (this.payType == 2) {
console.log('微信参赛')
console.log(params)
// 微信支付
wxPayCreateOrder(params, {
suc: res => {
uni.requestPayment({
provider: 'wxpay',
orderInfo: res.result,
success: res => {
this.$emit('ok')
this.close()
},
fail: err => {
util.printLog(err)
}
})
}
})
}else if (this.payType == 3) {
console.log('余额参赛')
console.log(params)
// 余额支付
balancePay(params, {
suc: res => {
this.$emit('ok')
this.close()
}
})
}
}
}
}
</script>
<style scoped>
.uni-popup-select {
background-color: #fff;
}
.uni-select-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
height: 50px;
position: relative;
border-bottom: 1rpx solid #E8E8E8;
}
.uni-select-title-text {
font-size: 34rpx;
font-weight: bold;
color: #020202;
text-align: center;
}
.uni-select-title .close {
position: absolute;
right: 30rpx;
top: 32rpx;
}
.close image {
width: 30rpx;
height: 30rpx;
}
.uni-select-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #F2F2F2;
}
.row .left {
flex: 1;
font-size: 26rpx;
color: #020202;
}
.left view:last-child {
font-size: 22rpx;
color: #AAAAAA;
}
.row .pay-type {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
font-size: 26rpx;
color: #020202;
}
.pay-type image {
width: 33rpx;
height: 33rpx;
margin-right: 10rpx;
}
.row .choose {
width: 30rpx;
height: 30rpx;
}
.row button {
width: 100vw;
height: 80rpx;
line-height: 88rpx;
color: white;
font-size: 30rpx;
background-color: #ff4229;
border-radius: 88rpx;
}
</style>
<template>
<view class="uni-popup-share">
<view class="uni-share-title"><text class="uni-share-title-text">{{title}}</text></view>
<view class="uni-share-content">
<view class="uni-share-content-box">
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
<text class="uni-share-text">{{item.text}}</text>
</view>
</view>
</view>
<view class="uni-share-button-box">
<button class="uni-share-button" @click="close">取消</button>
</view>
</view>
</template>
<script>
export default {
name: 'UniPopupShare',
props: {
title: {
type: String,
default: '分享到'
}
},
inject: ['popup'],
data() {
return {
imgBaseUrl: null,
bottomData: [{
text: '微信',
icon: 'https://huarenv1.oss-cn-beijing.aliyuncs.com/huaren_icon/WeChatdl.png',
name: 'wx'
},
{
text: '朋友圈',
icon: 'https://huarenv1.oss-cn-beijing.aliyuncs.com/huaren_icon/friend.png',
name: 'wx'
}
]
}
},
created() {
this.imgBaseUrl = this.$api.IMG_BASE_URL
},
methods: {
/**
* 选择内容
*/
select(item, index) {
this.$emit('select', {
item,
index
}, () => {
this.popup.close()
})
},
/**
* 关闭窗口
*/
close() {
this.popup.close()
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup-share {
background-color: #fff;
}
.uni-share-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
height: 40px;
}
.uni-share-title-text {
font-size: 14px;
color: #666;
}
.uni-share-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 10px;
}
.uni-share-content-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex-wrap: wrap;
width: 360px;
}
.uni-share-content-item {
width: 90px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
padding: 10px 0;
align-items: center;
}
.uni-share-content-item:active {
background-color: #f5f5f5;
}
.uni-share-image {
width: 30px;
height: 30px;
}
.uni-share-text {
margin-top: 10px;
font-size: 14px;
color: #3B4144;
}
.uni-share-button-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 10px 15px;
}
.uni-share-button {
flex: 1;
border-radius: 50px;
color: #666;
font-size: 16px;
}
.uni-share-button::after {
border-radius: 50px;
}
</style>
<template>
<view v-if="showPopup" class="uni-popup" :class="[popupstyle]" @touchmove.stop.prevent="clear">
<uni-transition v-if="maskShow" :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans"
@click="onTap" />
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper-box" @click.stop="clear">
<slot />
</view>
</uni-transition>
</view>
</template>
<script>
import uniTransition from '../uni-transition/uni-transition.vue'
import popup from './popup.js'
/**
* PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @value message 消息提示
* @value dialog 对话框
* @value share 底部分享示例
* @property {Boolean} animation = [ture|false] 是否开启动画
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
* @event {Function} change 打开关闭弹窗触发,e={show: false}
*/
export default {
name: 'UniPopup',
components: {
uniTransition
},
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
// message: 消息提示 ; dialog : 对话框
type: {
type: String,
default: 'center'
},
// maskClick
maskClick: {
type: Boolean,
default: true
}
},
provide() {
return {
popup: this
}
},
mixins: [popup],
watch: {
/**
* 监听type类型
*/
type: {
handler: function(newVal) {
this[this.config[newVal]]()
},
immediate: true
},
/**
* 监听遮罩是否可点击
* @param {Object} val
*/
maskClick(val) {
this.mkclick = val
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
maskClass: {
'position': 'fixed',
'bottom': 0,
'top': 0,
'left': 0,
'right': 0,
'backgroundColor': 'rgba(0, 0, 0, 0.4)'
},
transClass: {
'position': 'fixed',
'left': 0,
'right': 0,
},
maskShow: true,
mkclick: true,
popupstyle: 'top'
}
},
created() {
this.mkclick = this.maskClick
if (this.animation) {
this.duration = 300
} else {
this.duration = 0
}
},
methods: {
clear(e) {
// TODO nvue 取消冒泡
e.stopPropagation()
},
open() {
this.showPopup = true
this.$nextTick(() => {
new Promise(resolve => {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.showTrans = true
// fixed by mehaotian 兼容 app 端
this.$nextTick(() => {
resolve();
})
}, 50);
}).then(res => {
// 自定义打开事件
clearTimeout(this.msgtimer)
this.msgtimer = setTimeout(() => {
this.customOpen && this.customOpen()
}, 100)
this.$emit('change', {
show: true,
type: this.type
})
})
})
},
close(type) {
this.showTrans = false
this.$nextTick(() => {
this.$emit('change', {
show: false,
type: this.type
})
clearTimeout(this.timer)
// 自定义关闭事件
this.customOpen && this.customClose()
this.timer = setTimeout(() => {
this.showPopup = false
}, 300)
})
},
onTap() {
if (!this.mkclick) return
this.close()
},
/**
* 顶部弹出样式处理
*/
top() {
this.popupstyle = 'top'
this.ani = ['slide-top']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
}
},
/**
* 底部弹出样式处理
*/
bottom() {
this.popupstyle = 'bottom'
this.ani = ['slide-bottom']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
'bottom': 0
}
},
/**
* 中间弹出样式处理
*/
center() {
this.popupstyle = 'center'
this.ani = ['zoom-out', 'fade']
this.transClass = {
'position': 'fixed',
/* #ifndef APP-NVUE */
'display': 'flex',
'flexDirection': 'column',
/* #endif */
'bottom': 0,
'left': 0,
'right': 0,
'top': 0,
'justifyContent': 'center',
'alignItems': 'center'
}
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup {
position: fixed;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
opacity: 0;
}
.mask-ani {
transition-property: opacity;
transition-duration: 0.2s;
}
.uni-top-mask {
opacity: 1;
}
.uni-bottom-mask {
opacity: 1;
}
.uni-center-mask {
opacity: 1;
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
}
.top {
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
}
.bottom {
bottom: 0;
}
.uni-popup__wrapper-box {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
/* iphonex 等安全区设置,底部安全区适配 */
/* #ifndef APP-NVUE */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
}
.content-ani {
// transition: transform 0.3s;
transition-property: transform, opacity;
transition-duration: 0.2s;
}
.uni-top-content {
transform: translateY(0);
}
.uni-bottom-content {
transform: translateY(0);
}
.uni-center-content {
transform: scale(1);
opacity: 1;
}
</style>
<template>
<view :style="{ height: statusBarHeight }" class="uni-status-bar">
<slot />
</view>
</template>
<script>
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
export default {
name: 'UniStatusBar',
data() {
return {
statusBarHeight: statusBarHeight
}
}
}
</script>
<style lang="scss" scoped>
.uni-status-bar {
width: 750rpx;
height: 20px;
background-color: white;
// height: var(--status-bar-height);
}
</style>
<template>
<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject"
@click="change">
<slot></slot>
</view>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
*/
export default {
name: 'uniTransition',
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: Array,
default () {
return []
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default () {
return {}
}
}
},
data() {
return {
isShow: false,
transform: '',
ani: { in: '',
active: ''
}
};
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
this.close()
}
},
immediate: true
}
},
computed: {
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transfrom = ''
for (let i in styles) {
let line = this.toLine(i)
transfrom += line + ':' + styles[i] + ';'
}
return transfrom
}
},
created() {
// this.timer = null
// this.nextTick = (time = 50) => new Promise(resolve => {
// clearTimeout(this.timer)
// this.timer = setTimeout(resolve, time)
// return this.timer
// });
},
methods: {
change() {
this.$emit('click', {
detail: this.isShow
})
},
open() {
clearTimeout(this.timer)
this.isShow = true
this.transform = ''
this.ani.in = ''
for (let i in this.getTranfrom(false)) {
if (i === 'opacity') {
this.ani.in = 'fade-in'
} else {
this.transform += `${this.getTranfrom(false)[i]} `
}
}
this.$nextTick(() => {
setTimeout(() => {
this._animation(true)
}, 50)
})
},
close(type) {
clearTimeout(this.timer)
this._animation(false)
},
_animation(type) {
let styles = this.getTranfrom(type)
// #ifdef APP-NVUE
if(!this.$refs['ani']) return
animation.transition(this.$refs['ani'].ref, {
styles,
duration: this.duration, //ms
timingFunction: 'ease',
needLayout: false,
delay: 0 //ms
}, () => {
if (!type) {
this.isShow = false
}
this.$emit('change', {
detail: this.isShow
})
})
// #endif
// #ifndef APP-NVUE
this.transform = ''
for (let i in styles) {
if (i === 'opacity') {
this.ani.in = `fade-${type?'out':'in'}`
} else {
this.transform += `${styles[i]} `
}
}
this.timer = setTimeout(() => {
if (!type) {
this.isShow = false
}
this.$emit('change', {
detail: this.isShow
})
}, this.duration)
// #endif
},
getTranfrom(type) {
let styles = {
transform: ''
}
this.modeClass.forEach((mode) => {
switch (mode) {
case 'fade':
styles.opacity = type ? 1 : 0
break;
case 'slide-top':
styles.transform += `translateY(${type?'0':'-100%'}) `
break;
case 'slide-right':
styles.transform += `translateX(${type?'0':'100%'}) `
break;
case 'slide-bottom':
styles.transform += `translateY(${type?'0':'100%'}) `
break;
case 'slide-left':
styles.transform += `translateX(${type?'0':'-100%'}) `
break;
case 'zoom-in':
styles.transform += `scale(${type?1:0.8}) `
break;
case 'zoom-out':
styles.transform += `scale(${type?1:1.2}) `
break;
}
})
return styles
},
_modeClassArr(type) {
let mode = this.modeClass
if (typeof(mode) !== "string") {
let modestr = ''
mode.forEach((item) => {
modestr += (item + '-' + type + ',')
})
return modestr.substr(0, modestr.length - 1)
} else {
return mode + '-' + type
}
},
// getEl(el) {
// console.log(el || el.ref || null);
// return el || el.ref || null
// },
toLine(name) {
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
}
}
}
</script>
<style>
.uni-transition {
transition-timing-function: ease;
transition-duration: 0.3s;
transition-property: transform, opacity;
}
.fade-in {
opacity: 0;
}
.fade-active {
opacity: 1;
}
.slide-top-in {
/* transition-property: transform, opacity; */
transform: translateY(-100%);
}
.slide-top-active {
transform: translateY(0);
/* opacity: 1; */
}
.slide-right-in {
transform: translateX(100%);
}
.slide-right-active {
transform: translateX(0);
}
.slide-bottom-in {
transform: translateY(100%);
}
.slide-bottom-active {
transform: translateY(0);
}
.slide-left-in {
transform: translateX(-100%);
}
.slide-left-active {
transform: translateX(0);
opacity: 1;
}
.zoom-in-in {
transform: scale(0.8);
}
.zoom-out-active {
transform: scale(1);
}
.zoom-out-in {
transform: scale(1.2);
}
</style>
## 插件说明
> 这是 `v-tabs` 插件的升级版本,参数上有很大变动,支持 `H5` `小程序` `手机端`,如果是在之前的插件上升级的话,请注意参数的变更,触发的事件没有变更。
## 使用说明
### 1、最基本用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
export default {
data() {
return {
current: 0,
tabs: ['军事', '国内', '新闻新闻', '军事', '国内', '新闻', '军事', '国内', '新闻']
}
},
methods: {
changeTab(index) {
console.log('当前选中的项:' + index)
}
}
}
```
### 2、平铺整个屏幕
- 视图文件
```html
<v-tabs v-model="activeTab" :scroll="false" :tabs="['全部', '进行中', '已完成']"></v-tabs>
```
- 脚本文件
```js
export default {
data() {
return {
activeTab: 0
}
}
}
```
### 3、胶囊用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" :pills="true" line-height="0" activeColor="#fff" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
data() {
return {
current: 2,
tabs: [
'军事',
'国内',
'新闻新闻',
'军事',
'国内',
'新闻',
'军事',
'国内',
'新闻',
],
},
methods: {
changeTab(index) {
console.log('当前选中索引:' + index)
}
}
}
```
## 文档说明
### 1、属性说明
| 参数 | 类型 | 默认值 | 说明 |
| :---------------: | :-----: | :-------: | :----------------------------------------: |
| value | Number | 0 | 必传(双向绑定的值) |
| color | String | '#333' | 默认文字颜色 |
| activeColor | String | '#2979ff' | 选中文字的颜色 |
| fontSize | String | '28rpx' | 默认文字大小(rpx 或 px) |
| bold | Boolean | true | 是否加粗选中项 |
| scroll | Boolean | true | 是否显示滚动条,平铺设置 false |
| height | String | '70rpx' | tab 高度(rpx 或 px) |
| lineHeight | String | '10rpx' | 滑块高度(rpx 或 px) |
| lineColor | String | '#2979ff' | 滑块的颜色 |
| lineScale | Number | 0.5 | 滑块宽度缩放值 |
| lineRadius | String | '10rpx' | 滑块圆角宽度(rpx 或 px) |
| pills | Boolean | false | 是否开启胶囊 |
| pillsColor | String | '#2979ff' | 胶囊背景颜色(rpx 或 px) |
| pillsBorderRadius | String | '10rpx' | 胶囊圆角宽度(rpx 或 px) |
| field | String | '' | 如果 tabs 子项是对象,输入需要展示的键名 |
| bgColor | String | '#fff' | 背景色,支持 linear-gradient 渐变 |
| padding | String | '0' | 整个 tab padding 属性 |
| fixed | Boolean | false | 是否固定在顶部 |
| paddingItem | String | '0 22rpx' | 选项的边距(设置上下不生效,需要设置高度) |
### 2、事件说明
| 名称 | 参数 | 说明 |
| :----: | :---: | :--------------------------------: |
| change | index | 改变选中项触发, index 选中项的下标 |
## 更新日志
### 2020-09-24
1. 修复 `v-tabs` 第一次可能出现第一个标签显示不完整的情况
2. 修改了 `pages/tabs/order` 示例文件
### 2020-09-21
1. 修复添加 `fixed` 属性后,滚动条无效
2. 修复选项很少的情况下,下划线计算计算错误
3. 新增 `paddingItem` 属性,设置选项左右边距(上下边距需要设置 `height` 属性,或者设置 `padding` 属性)
**写在最后:**
欢迎各位老铁反馈 bug ,本人后端 PHP 一枚,只是应为感兴趣前端,自己琢磨,自己搞。如果你在使用的过程中有什么不合理,需要优化的,都可以在下面评论(或加我 QQ: 1207791534),本人看见后回复、修正,感谢。
### 2020-09-17
1. 紧急修复 bug,横向滑动不了的情况
### 2020-09-16
1. 新增 `fixed` 属性,是否固定在顶部,示例地址:`pages/tabs/tabs-static`
2. 优化之前的页面结构
**注意:**
1. 使用 `padding` 属性的时候,尽量不要左右边距,会导致下划线位置不对
2. 如果不绑定 `v-model` 会导致 `change` 事件改变的时候,下划线不跟随问题
### 2020-09-09
1. 修复 `width` 错误,dom 加载的时候没有及时获取到 `data` 属性导致的。
### 2020-08-29
1. 优化异步改变 `tabs` 后,下划线不初始化问题
2. `github` 地址上有图 2 的源码,需要的自行下载,页面路径:`pages/tabs/order`
### 2020-08-20
1. 优化 `节点查询``选中渲染`
2. 优化支付宝中 `createSelectorQuery()` 的影响
### 2020-08-19
1. 优化 `change` 事件触发机制
### 2020-08-16
1. 修改默认高度为 `70rpx`
2. 新增属性 `bgColor`,可设置背景颜色,默认 `#fff`
3. 新增整个 `tab``padding` 属性,默认 `0`
### 2020-08-13
1. 全新的 `v-tabs 2.0`
2. 支持 `H5` `小程序` `APP`
3. 属性高度可配置
## 预览
![v-tabs 2.0.1.gif](https://tva1.sinaimg.cn/large/007S8ZIlgy1ghsv40mj76g30ai0i2tsd.gif)
![v-tabs 2.0.2.gif](https://img-cdn-aliyun.dcloud.net.cn/stream/plugin_screens/42f3a920-a674-11ea-8a24-ffee00625e2e_1.png?v=1597912963)
<template>
<view :id="elId" class="v-tabs">
<scroll-view
id="scrollContainer"
:scroll-x="scroll"
:scroll-left="scroll ? scrollLeft : 0"
:scroll-with-animation="scroll"
:style="{ position: fixed ? 'fixed' : 'relative', zIndex: 1993 }"
>
<view
class="v-tabs__container"
:style="{
display: scroll ? 'inline-flex' : 'flex',
whiteSpace: scroll ? 'nowrap' : 'normal',
background: bgColor,
height,
padding
}"
>
<view
class="v-tabs__container-item"
v-for="(v, i) in tabs"
:key="i"
:style="{
color: current == i ? activeColor : color,
fontSize: current == i ? fontSize : fontSize,
fontWeight: bold && current == i ? 'bold' : '',
justifyContent: !scroll ? 'center' : '',
flex: scroll ? '' : 1,
padding: paddingItem
}"
@click="change(i)"
>
{{ field ? v[field] : v }}
</view>
<view
v-if="!pills"
class="v-tabs__container-line"
:style="{
background: lineColor,
width: lineWidth + 'px',
height: lineHeight,
borderRadius: lineRadius,
left: lineLeft + 'px',
transform: `translateX(-${lineWidth / 2}px)`
}"
></view>
<view
v-else
class="v-tabs__container-pills"
:style="{
background: pillsColor,
borderRadius: pillsBorderRadius,
left: pillsLeft + 'px',
width: currentWidth + 'px',
height
}"
></view>
</view>
</scroll-view>
<view
class="v-tabs__placeholder"
:style="{
height: fixed ? height : '0',
padding
}"
></view>
</view>
</template>
<script>
/**
* v-tabs
* @property {Number} value 选中的下标
* @property {Array} tabs tabs 列表
* @property {String} bgColor = '#fff' 背景颜色
* @property {String} color = '#333' 默认颜色
* @property {String} activeColor = '#2979ff' 选中文字颜色
* @property {String} fontSize = '28rpx' 默认文字大小
* @property {String} activeFontSize = '28rpx' 选中文字大小
* @property {Boolean} bold = [true | false] 选中文字是否加粗
* @property {Boolean} scroll = [true | false] 是否滚动
* @property {String} height = '60rpx' tab 的高度
* @property {String} lineHeight = '10rpx' 下划线的高度
* @property {String} lineColor = '#2979ff' 下划线的颜色
* @property {Number} lineScale = 0.5 下划线的宽度缩放比例
* @property {String} lineRadius = '10rpx' 下划线圆角
* @property {Boolean} pills = [true | false] 是否胶囊样式
* @property {String} pillsColor = '#2979ff' 胶囊背景色
* @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
* @property {String} field 如果是对象,显示的键名
* @property {Boolean} fixed = [true | false] 是否固定
* @property {String} paddingItem = '0 22rpx' 选项的边距
*
* @event {Function(current)} change 改变标签触发
*/
export default {
props: {
value: {
type: Number,
default: 0
},
tabs: {
type: Array,
default() {
return []
}
},
bgColor: {
type: String,
default: '#fff'
},
padding: {
type: String,
default: '0'
},
color: {
type: String,
default: '#333'
},
activeColor: {
type: String,
default: '#2979ff'
},
fontSize: {
type: String,
default: '28rpx'
},
activeFontSize: {
type: String,
default: '32rpx'
},
bold: {
type: Boolean,
default: true
},
scroll: {
type: Boolean,
default: true
},
height: {
type: String,
default: '70rpx'
},
lineColor: {
type: String,
default: '#2979ff'
},
lineHeight: {
type: String,
default: '10rpx'
},
lineScale: {
type: Number,
default: 0.5
},
lineRadius: {
type: String,
default: '10rpx'
},
pills: {
type: Boolean,
deafult: false
},
pillsColor: {
type: String,
default: '#2979ff'
},
pillsBorderRadius: {
type: String,
default: '10rpx'
},
field: {
type: String,
default: ''
},
fixed: {
type: Boolean,
default: false
},
paddingItem: {
type: String,
default: '0 22rpx'
}
},
data() {
return {
elId: '',
lineWidth: 30,
currentWidth: 0, // 当前选项的宽度
lineLeft: 0, // 滑块距离左侧的位置
pillsLeft: 0, // 胶囊距离左侧的位置
scrollLeft: 0, // 距离左边的位置
containerWidth: 0, // 容器的宽度
current: 0 // 当前选中项
}
},
watch: {
value(newVal) {
this.current = newVal
this.$nextTick(() => {
this.getTabItemWidth()
})
},
current(newVal) {
this.$emit('input', newVal)
},
tabs(newVal) {
this.$nextTick(() => {
this.getTabItemWidth()
})
}
},
methods: {
// 产生随机字符串
randomString(len) {
len = len || 32
let $chars =
'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
let maxPos = $chars.length
let pwd = ''
for (let i = 0; i < len; i++) {
pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
}
return pwd
},
// 切换事件
change(index) {
if (this.current !== index) {
this.current = index
this.$emit('change', index)
}
},
// 获取左移动位置
getTabItemWidth() {
let query = uni
.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
// 获取容器的宽度
query
.select(`#scrollContainer`)
.boundingClientRect((data) => {
if (!this.containerWidth && data) {
this.containerWidth = data.width
}
})
.exec()
// 获取所有的 tab-item 的宽度
query
.selectAll('.v-tabs__container-item')
.boundingClientRect((data) => {
if (!data) {
return
}
let lineLeft = 0
let currentWidth = 0
if (data) {
for (let i = 0; i < data.length; i++) {
if (i < this.current) {
lineLeft += data[i].width
} else if (i == this.current) {
currentWidth = data[i].width
} else {
break
}
}
}
// 当前滑块的宽度
this.currentWidth = currentWidth
// 缩放后的滑块宽度
this.lineWidth = currentWidth * this.lineScale * 1
// 滑块作移动的位置
this.lineLeft = lineLeft + currentWidth / 2
// 胶囊距离左侧的位置
this.pillsLeft = lineLeft
// 计算滚动的距离左侧的位置
if (this.scroll) {
this.scrollLeft = this.lineLeft - this.containerWidth / 2
}
})
.exec()
}
},
mounted() {
this.elId = 'xfjpeter_' + this.randomString()
this.current = this.value
this.$nextTick(() => {
this.getTabItemWidth()
})
}
}
</script>
<style lang="scss" scoped>
.v-tabs {
width: 100%;
box-sizing: border-box;
overflow: hidden;
::-webkit-scrollbar {
display: none;
}
&__container {
min-width: 100%;
position: relative;
display: inline-flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
&-item {
display: flex;
align-items: center;
height: 100%;
position: relative;
z-index: 10;
// padding: 0 11px;
transition: all 0.3s;
white-space: nowrap;
}
&-line {
position: absolute;
bottom: 0;
transition: all 0.3s linear;
}
&-pills {
position: absolute;
transition: all 0.3s linear;
z-index: 9;
}
}
}
</style>
This diff is collapsed. Click to expand it.
// uni框架的方法封装
const main = {
// 显示消息提示窗
showToast: (title = '', duration = 1500, icon = 'none') => {
uni.showToast({
icon: icon,
title: title,
duration: duration
})
},
// 隐藏消息提示窗
hideToast: () => {
uni.hideToast()
},
// 显示loadding提示窗 需主动调用 hideLoading 才能关闭提示框
showLoading: (title = '') => {
uni.showLoading({
title: title
})
},
// 隐藏loadding提示窗
hideLoading: (duration = 0) => {
setTimeout(function () {
uni.hideLoading()
}, duration)
},
// 显示模态提示框
showModal: (content = '', title = '提示', showCancel = true, confirmText = '确定', cancelText = '取消', confirmColor = '#50A8FC', cancelColor = '#9b9b9b') => {
if (content && content instanceof Object) {
let data = content
title = data.title || title
showCancel = data.showCancel || showCancel
confirmText = data.confirmText || confirmText
cancelText = data.cancelText || cancelText
confirmColor = data.confirmColor || confirmColor
cancelColor = data.cancelColor || cancelColor
content = data.content || ''
}
var promise = new Promise(function (resolve, reject) {
uni.showModal({
title: title, // 标题
content: content, // 内容
showCancel: showCancel, // 是否显示取消按钮
confirmText: confirmText, // 确认按钮文字
cancelText: cancelText, // 取消按钮文字
confirmColor: confirmColor, // 确认按钮颜色
cancelColor: cancelColor, // 取消按钮颜色
success: function (res) {
if (res.confirm) {
resolve(true)
} else if (res.cancel) {
resolve(false)
}
}
})
})
return promise
},
// 显示从底部弹出的操作菜单
showActionSheet: (itemList = [], itemColor = '#333333') => {
var promise = new Promise(function (resolve, reject) {
uni.showActionSheet({
itemList: itemList, // 菜单列表
itemColor: itemColor, // 选项文字
success (res) {
resolve(res.tapIndex)
},
fail (res) {
resolve(false)
}
})
})
return promise
},
// 动态设置当前页面的标题
setNavigationBarTitle: (title = '') => {
uni.setNavigationBarTitle({
title: title
})
},
//将页面滚动到目标位置
pageScrollTo: (scrollTop, selector, duration = 300) => {
uni.pageScrollTo({
scrollTop: scrollTop,
selector: selector, // 选择器(id、class)
duration: duration
})
},
//获取当前位置(经度、纬度)
getLocation: (type = 'wgs84') => {
var promise = new Promise((resolve, reject) => {
uni.getLocation({
type: type,
success: res => {
resolve(res)
},
fail: err => {
reject(err)
}
})
})
return promise
},
// 复制文本内容
setClipboardData: (data, msg = '') => {
uni.setClipboardData({
data: data, // 复制的文本
success: function () {
if (msg) {
main.showToast(msg, 1000)
}
}
})
},
// 支付
requestPayment: (type, orderInfo) => {
var promise = new Promise (function (resolve, reject) {
uni.requestPayment({
provider: type,
orderInfo: orderInfo,
success: (res) => {
resolve (res)
},
fail: (err) => {
// console.log('err', err)
}
})
})
return promise
},
// 登录
uniLogin: (type) => {
var promise = new Promise (function (resolve, reject) {
uni.login({
provider: type,
success: (res) => {
resolve(res)
},
fail: (err) => {
reject(err)
}
})
})
return promise
}
}
export default main
\ No newline at end of file
// 配置路由
const path = {
// 跳转到非tabBar的子页面
navigateTo (url) {
uni.navigateTo({
url: url
})
},
// 跳转到tabBar页面
switchTab (url) {
uni.switchTab({
url: url
})
},
// 重定向跳转
redirectTo (url) {
uni.redirectTo({
url: url
})
},
// 关闭所有页面,跳转一个新页面
reLaunch (url) {
uni.reLaunch({
url: url
})
},
// 返回上一个页面
navigateBack (count) {
uni.navigateBack({
delta: count
})
},
// 预加载页面,打开时速度更快
preloadPage (url) {
uni.preloadPage({
url: url
})
}
}
export default path
// 缓存封装
const store = {
// 存缓存
setStorage: (key, data) => {
uni.setStorage({
key: key,
data: data
})
},
// 存缓存(同步)
setStorageSync: (key, data) => {
try {
uni.setStorageSync(key, data)
} catch (e) {
// error
}
},
// 取缓存 (异步)
getStorage(key) {
var promise = new Promise((resolve, reject) => {
uni.getStorage({
key: key,
success (res) {
resolve(res.data)
},
fail (err) {
},
complete (res) {
}
})
})
return promise
},
// 取缓存(同步)
getStorageSync(key) {
return uni.getStorageSync(key)
},
// 移除缓存(异步)
removeStorage(key) {
uni.removeStorage({
key: key
})
},
// 移除缓存(同步)
removeStorageSync(key) {
uni.removeStorageSync(key)
},
// 清空缓存(异步)
clearStorage: () => {
uni.clearStorage()
},
//清空缓存(同步)
clearStorageSync: () => {
uni.clearStorageSync()
}
}
export default store
\ No newline at end of file
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [hour, minute].map(formatNumber).join(':')
}
const formatDate = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('-')
}
const showIntervalTime = (currentTime, nowTime) => {
var time = Math.floor((nowTime - currentTime) / 1000)
var str = ''
if (time < 60) {
str = '1分钟'
} else if (time > 60 && time < 3600) {
str = Math.ceil(time / 60) + '分钟'
} else if (time > 3600 && time < 3600 * 24) {
str = Math.ceil(time / 3600) + '小时'
} else {
str = Math.ceil(time / (3600 * 24)) + '天'
}
return str
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
const getDistance = (la1, lo1, la2, lo2) => {
var La1 = la1 * Math.PI / 180.0
var La2 = la2 * Math.PI / 180.0
var La3 = La1 - La2
var Lb3 = lo1 * Math.PI / 180.0 - lo2 * Math.PI / 180.0
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(La3 / 2), 2) + Math.cos(La1) * Math.cos(La2) * Math.pow(Math.sin(
Lb3 / 2), 2)))
s = s * 6378.137
s = Math.round(s * 10000) / 10000
s = s > 1 ? s.toFixed(2) + 'km' : (s * 1000).toFixed(0) + 'm'
return s
}
const hidePhone = (phone) => {
if (phone) {
return phone.substring(0, 3) + '****' + phone.substring(7)
} else {
return ''
}
}
//从存储去获取用户信息
const getUsersInfoByStore = () => {
var obj = {}
if (uni.getStorageSync('user')) {
let userInfoStr = uni.getStorageSync('user')
obj = JSON.parse(userInfoStr)
}
return obj
}
// 搜索历史
const getSearchHistory = () => {
let history = []
let historyStr = uni.getStorageSync('search')
if (historyStr) {
history = historyStr.split(',')
}
return history
}
// 设置搜索历史
const addSearchHistory = (word) => {
let history = getSearchHistory()
if (history.indexOf(word) != -1) {
history.splice(history.indexOf(word), 1)
}
history.unshift(word)
uni.setStorageSync('search', history.join(','))
}
// 清空搜索历史
const clearSearchHistory = () => {
uni.setStorageSync('search', '')
}
// 微信分享 朋友圈/好友
const wetchatShare = (scene, href, title, summary, imageUrl) => {
//如果没图片就用logo图
var imgUrl = (imageUrl.length > 0) ? imageUrl : 'https://yun-kuang.oss-cn-hangzhou.aliyuncs.com/upload/test/ic_logo_1603180073960.png';
uni.share({
provider: "weixin",
scene: scene,
type: 0,
href: href,
title: title,
summary: summary,
imageUrl: imgUrl,//decodeURIComponent(imageUrl),//还是显示不了
success: function(res) {
uni.showToast({
title: '分享成功',
icon: 'none'
})
},
fail: function(err) {
console.log("fail:" + JSON.stringify(err));
uni.showToast({
title: '分享失败',
icon: 'none'
})
}
});
}
//转rgb
//https://blog.csdn.net/mossbaoo/article/details/93484635
const colorRgb = (oldColor,rgb) => {
// 16进制颜色值的正则
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
// 把颜色值变成小写
var color = oldColor.toLowerCase();
if (reg.test(color)) {
// 如果只有三位的值,需变成六位,如:#fff => #ffffff
if (color.length === 4) {
var colorNew = "#";
for (var i = 1; i < 4; i += 1) {
colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
}
color = colorNew;
}
// 处理六位的颜色值,转为RGB
var colorChange = [];
for (var i = 1; i < 7; i += 2) {
colorChange.push(parseInt("0x" + color.slice(i, i + 2)));
}
return "RGB(" + colorChange.join(",") + "," + rgb +")";
} else {
return color;
}
}
module.exports = {
formatTime: formatTime,
formatDate: formatDate,
showIntervalTime: showIntervalTime,
getDistance: getDistance,
hidePhone: hidePhone,
getSearchHistory: getSearchHistory,
addSearchHistory: addSearchHistory,
clearSearchHistory: clearSearchHistory,
getUsersInfoByStore: getUsersInfoByStore,
wetchatShare: wetchatShare,
colorRgb:colorRgb,
printLog: function(msg) {
console.log(msg)
},
showLoading: function() {
uni.showLoading({
title: '加载中'
})
},
closeLoading: function() {
uni.hideLoading()
},
showToast: function(msg) {
uni.showToast({
title: msg,
icon: 'none'
})
},
isLogin: function() {
return uni.getStorageSync('token')
},
goLogin: function() {
uni.removeStorageSync('token')
uni.removeStorageSync('user')
uni.reLaunch({
url: '/pages/index/login'
})
},
//是否安装微信
isInstallWetchat: function() {
var isInstall = false;
// 判断第三方程序(微信) 是否安装
if(plus.runtime.isApplicationExist({pname:'com.hexagon.sandstone',action:'weixin://'})){
console.log("微信应用已安装");
isInstall = true;
}else{
console.log("微信应用未安装");
isInstall = false;
}
return isInstall;
}
}
function AMapWX(a){this.key=a.key,this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"}}AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(a){var c=a.longitude+","+a.latitude;wx.setStorage({key:"userLocation",data:c}),b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(a){a.data&&b(a.data)}}),a.fail({errCode:"0",errMsg:c.errMsg||""})}})},AMapWX.prototype.getRegeo=function(a){function c(c){var d=b.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:b.key,location:c,extensions:"all",s:d.s,platform:d.platform,appname:b.key,sdkversion:d.sdkversion,logversion:d.logversion},method:"GET",header:{"content-type":"application/json"},success:function(b){var d,e,f,g,h,i,j,k,l;b.data.status&&"1"==b.data.status?(d=b.data.regeocode,e=d.addressComponent,f=[],g="",d&&d.roads[0]&&d.roads[0].name&&(g=d.roads[0].name+"附近"),h=c.split(",")[0],i=c.split(",")[1],d.pois&&d.pois[0]&&(g=d.pois[0].name+"附近",j=d.pois[0].location,j&&(h=parseFloat(j.split(",")[0]),i=parseFloat(j.split(",")[1]))),e.provice&&f.push(e.provice),e.city&&f.push(e.city),e.district&&f.push(e.district),e.streetNumber&&e.streetNumber.street&&e.streetNumber.number?(f.push(e.streetNumber.street),f.push(e.streetNumber.number)):(k="",d&&d.roads[0]&&d.roads[0].name&&(k=d.roads[0].name),f.push(k)),f=f.join(""),l=[{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:g,longitude:h,latitude:i,id:0,regeocodeData:d}],a.success(l)):a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}var b=this;a.location?c(a.location):b.getWxLocation(a,function(a){c(a)})},AMapWX.prototype.getWeather=function(a){function d(d){var e="base";a.type&&"forecast"==a.type&&(e="all"),wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:b.key,city:d,extensions:e,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion},method:"GET",header:{"content-type":"application/json"},success:function(b){function c(a){var b={city:{text:"城市",data:a.city},weather:{text:"天气",data:a.weather},temperature:{text:"温度",data:a.temperature},winddirection:{text:"风向",data:a.winddirection+"风"},windpower:{text:"风力",data:a.windpower+"级"},humidity:{text:"湿度",data:a.humidity+"%"}};return b}var d,e;b.data.status&&"1"==b.data.status?b.data.lives?(d=b.data.lives,d&&d.length>0&&(d=d[0],e=c(d),e["liveData"]=d,a.success(e))):b.data.forecasts&&b.data.forecasts[0]&&a.success({forecast:b.data.forecasts[0]}):a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}function e(e){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:b.key,location:e,extensions:"all",s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion},method:"GET",header:{"content-type":"application/json"},success:function(b){var c,e;b.data.status&&"1"==b.data.status?(e=b.data.regeocode,e.addressComponent?c=e.addressComponent.adcode:e.aois&&e.aois.length>0&&(c=e.aois[0].adcode),d(c)):a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}var b=this,c=b.requestConfig;a.city?d(a.city):b.getWxLocation(a,function(a){e(a)})},AMapWX.prototype.getPoiAround=function(a){function d(d){var e={key:b.key,location:d,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.querytypes&&(e["types"]=a.querytypes),a.querykeywords&&(e["keywords"]=a.querykeywords),wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(b){var c,d,e,f;if(b.data.status&&"1"==b.data.status){if(b=b.data,b&&b.pois){for(c=[],d=0;d<b.pois.length;d++)e=0==d?a.iconPathSelected:a.iconPath,c.push({latitude:parseFloat(b.pois[d].location.split(",")[1]),longitude:parseFloat(b.pois[d].location.split(",")[0]),iconPath:e,width:22,height:32,id:d,name:b.pois[d].name,address:b.pois[d].address});f={markers:c,poisData:b.pois},a.success(f)}}else a.fail({errCode:b.data.infocode,errMsg:b.data.info})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})}var b=this,c=b.requestConfig;a.location?d(a.location):b.getWxLocation(a,function(a){d(a)})},AMapWX.prototype.getStaticmap=function(a){function f(b){c.push("location="+b),a.zoom&&c.push("zoom="+a.zoom),a.size&&c.push("size="+a.size),a.scale&&c.push("scale="+a.scale),a.markers&&c.push("markers="+a.markers),a.labels&&c.push("labels="+a.labels),a.paths&&c.push("paths="+a.paths),a.traffic&&c.push("traffic="+a.traffic);var e=d+c.join("&");a.success({url:e})}var e,b=this,c=[],d="https://restapi.amap.com/v3/staticmap?";c.push("key="+b.key),e=b.requestConfig,c.push("s="+e.s),c.push("platform="+e.platform),c.push("appname="+e.appname),c.push("sdkversion="+e.sdkversion),c.push("logversion="+e.logversion),a.location?f(a.location):b.getWxLocation(a,function(a){f(a)})},AMapWX.prototype.getInputtips=function(a){var b=this,c=b.requestConfig,d={key:b.key,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.location&&(d["location"]=a.location),a.keywords&&(d["keywords"]=a.keywords),a.type&&(d["type"]=a.type),a.city&&(d["city"]=a.city),a.citylimit&&(d["citylimit"]=a.citylimit),wx.request({url:"https://restapi.amap.com/v3/assistant/inputtips",data:d,method:"GET",header:{"content-type":"application/json"},success:function(b){b&&b.data&&b.data.tips&&a.success({tips:b.data.tips})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})},AMapWX.prototype.getDrivingRoute=function(a){var b=this,c=b.requestConfig,d={key:b.key,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.origin&&(d["origin"]=a.origin),a.destination&&(d["destination"]=a.destination),a.strategy&&(d["strategy"]=a.strategy),a.waypoints&&(d["waypoints"]=a.waypoints),a.avoidpolygons&&(d["avoidpolygons"]=a.avoidpolygons),a.avoidroad&&(d["avoidroad"]=a.avoidroad),wx.request({url:"https://restapi.amap.com/v3/direction/driving",data:d,method:"GET",header:{"content-type":"application/json"},success:function(b){b&&b.data&&b.data.route&&a.success({paths:b.data.route.paths,taxi_cost:b.data.route.taxi_cost||""})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})},AMapWX.prototype.getWalkingRoute=function(a){var b=this,c=b.requestConfig,d={key:b.key,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.origin&&(d["origin"]=a.origin),a.destination&&(d["destination"]=a.destination),wx.request({url:"https://restapi.amap.com/v3/direction/walking",data:d,method:"GET",header:{"content-type":"application/json"},success:function(b){b&&b.data&&b.data.route&&a.success({paths:b.data.route.paths})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})},AMapWX.prototype.getTransitRoute=function(a){var b=this,c=b.requestConfig,d={key:b.key,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.origin&&(d["origin"]=a.origin),a.destination&&(d["destination"]=a.destination),a.strategy&&(d["strategy"]=a.strategy),a.city&&(d["city"]=a.city),a.cityd&&(d["cityd"]=a.cityd),wx.request({url:"https://restapi.amap.com/v3/direction/transit/integrated",data:d,method:"GET",header:{"content-type":"application/json"},success:function(b){if(b&&b.data&&b.data.route){var c=b.data.route;a.success({distance:c.distance||"",taxi_cost:c.taxi_cost||"",transits:c.transits})}},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})},AMapWX.prototype.getRidingRoute=function(a){var b=this,c=b.requestConfig,d={key:b.key,s:c.s,platform:c.platform,appname:b.key,sdkversion:c.sdkversion,logversion:c.logversion};a.origin&&(d["origin"]=a.origin),a.destination&&(d["destination"]=a.destination),wx.request({url:"https://restapi.amap.com/v4/direction/bicycling",data:d,method:"GET",header:{"content-type":"application/json"},success:function(b){b&&b.data&&b.data.data&&a.success({paths:b.data.data.paths})},fail:function(b){a.fail({errCode:"0",errMsg:b.errMsg||""})}})},module.exports.AMapWX=AMapWX;
\ No newline at end of file
import Vue from 'vue'
import App from './App'
import path from './config/router.js'
import store from './config/store.js'
import main from './config/main.js'
import api from './config/api.js'
Vue.config.productionTip = false
Vue.prototype.$path = path
Vue.prototype.$store = store
Vue.prototype.$main = main
Vue.prototype.$api = api
App.mpType = 'app'
// Vue.util.productionTip = false
const app = new Vue({
...App,
path,
store,
main,
api
})
app.$mount()
{
"name" : "华仁优选",
"appid" : "__UNI__E592995",
"description" : "华仁优选",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {
"Payment" : {},
"OAuth" : {},
"Share" : {},
"Maps" : {}
},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {
"privacyDescription" : {
"NSLocationWhenInUseUsageDescription" : "华仁访问您的位置,仅仅显示你当前的位置,从而更快得到你附近咨讯和供应商品数据,该信息数据不会上传到服务器",
"NSLocationAlwaysUsageDescription" : "华仁访问您的位置,仅仅显示你当前的位置,从而更快得到你附近咨讯和供应商品数据,该信息数据不会上传到服务器",
"NSLocationAlwaysAndWhenInUseUsageDescription" : "华仁访问您的位置,仅仅显示你当前的位置,从而更快得到你附近咨讯和供应商品数据,该信息数据不会上传到服务器"
}
},
/* SDK配置 */
"sdkConfigs" : {
"ad" : {},
"payment" : {
"alipay" : {
"__platform__" : [ "android" ]
},
"weixin" : {
"__platform__" : [ "android" ],
"appid" : "wx5ffb0a232bf3fc9b",
"UniversalLinks" : "https://tr5z78.xinstall.top/tolink/"
}
},
"oauth" : {
"weixin" : {
"appid" : "wx5ffb0a232bf3fc9b",
"appsecret" : "ffb9665edfbbdeeebba04c01e5272a9d",
"UniversalLinks" : "https://tr5z78.xinstall.top/tolink/"
}
},
"share" : {
"weixin" : {
"appid" : "wx5ffb0a232bf3fc9b",
"UniversalLinks" : "https://tr5z78.xinstall.top/tolink/"
}
},
"maps" : {
"amap" : {
"appkey_ios" : "67250069dd9762ec0b12b6b49a2150f9",
"appkey_android" : "892e741ef93a9552647aec2826f038c0"
}
},
"geolocation" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},
"splashscreen" : {
"androidStyle" : "common"
}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "wx5990f741872f4974",
"setting" : {
"urlCheck" : false,
"es6" : true,
"minified" : false
},
"optimization" : {
"subPackages" : true
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "你的位置信息将用于小程序位置接口的效果展示"
}
}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"mp-qq" : {
"uniStatistics" : {
"enable" : false
}
},
"h5" : {
"title" : "华仁优选",
"domain" : "http://hr.jsonpro.cn"
}
}
{
"pages": [
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path" : "pages/index/home",
"style" :
{
"navigationBarTitleText": "台粮道",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/goodsDetail",
"style": {
"navigationBarTitleText": "商品详情",
"app-plus": {
"titleNView": {
"type": "transparent"
}
}
}
},
{
"path": "pages/my/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarBackgroundColor": "#FFFFFF",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/myWallet",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/cashOut",
"style": {
"navigationBarTitleText": "提现",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/cashOutRecord",
"style": {
"navigationBarTitleText": "提现记录",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/coupon",
"style": {
"navigationBarTitleText": "优惠券",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/manageAdress",
"style": {
"navigationBarTitleText": "管理收货地址",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/creatAdress",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/balanceRecord",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/signForDetail",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/setting",
"style": {
"navigationBarTitleText": "设置",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/aboutUs",
"style": {
"navigationBarTitleText": "关于我们",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/myCollection",
"style": {
"navigationBarTitleText": "我的收藏",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/inviteFriend",
"style": {
"navigationBarTitleText": "邀请好友",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/myOrder",
"style": {
"navigationBarTitleText": "我的订单",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/orderDetail",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/login",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/bind",
"style": {
"navigationBarTitleText": "绑定手机"
}
},
{
"path": "pages/my/feedback",
"style": {
"navigationBarTitleText": "意见反馈",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/detail",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/index/webView",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/my/myTeam",
"style" :
{
"navigationBarTitleText": "我的团队",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/my/setUserInfo",
"style" :
{
"navigationBarTitleText": "个人资料",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/shopping/index",
"style" :
{
"navigationStyle": "custom",
"navigationBarTitleText": "",
// "onReachBottomDistance": 80,
"enablePullDownRefresh": true
}
},
{
"path" : "pages/shopping/shopCar",
"style" :
{
"navigationBarTitleText": "购物车",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/shopping/confirmOrder",
"style" :
{
"navigationBarTitleText": "确认订单",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/shopping/orderSettle",
"style" :
{
"navigationBarTitleText": "确认订单",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/shopping/payResult",
"style" :
{
"navigationBarTitleText": "支付结果",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/index/more",
"style" :
{
"navigationBarTitleText": "更多",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/my/manger",
"style" :
{
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/my/rollOut",
"style" :
{
"navigationBarTitleText": "转出到余额",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#FFF",
"backgroundColor": "#F8F8F8"
},
"condition": {
//模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "", //模式名称
"path": "", //启动页面,必选
"query": "" //启动参数,在页面的onLoad函数里面得到
}]
},
"easycom": {
"autoscan": true,
"custom": {
"l-(.*)": "@/components/$1/index.vue"
}
}
}
<template>
<view class="white-content">
<view class="content">
<view class="input-row">
<label>手机号</label>
<input v-model="phone" type="digit" maxlength="11" placeholder="请输入手机号码" @blur="handleBlur" />
</view>
<view class="input-row">
<label>验证码</label>
<input v-model="smsCode" type="digit" maxlength="6" placeholder="请输入验证码" />
<button @click="getSmsCode" :disabled="!phone || phone.length < 11 || time < 60">{{codeTip}}</button>
</view>
</view>
<button class="theme" :disabled="!phone || phone.length < 11 || !smsCode || smsCode.length < 6 " @click="gobind">绑定</button>
</view>
</template>
<script>
import util from '@/config/util.js'
import {
checkCode,
bindWx
} from '@/config/api.js'
export default {
data() {
return {
phone: null,
smsCode: null,
codeTip: '获取验证码',
time: 60,
userInfo: null
};
},
onLoad(options) {
Object.assign(this, this.$options.data())
if (options.data) {
this.userInfo = JSON.parse(options.data)
} else {
util.showToast('数据缺失,请重试!')
uni.navigateBack({
delta: 1
})
}
},
methods: {
getSmsCode() {
var that = this
if (that.time != 60) {
return
}
var params = {
phone: that.phone
}
checkCode(params, {
suc: (res) => {
util.showToast('验证码发送成功');
that.startCountDown()
}
})
},
startCountDown() {
var that = this
var id = setInterval(function() {
var time = that.time
var str = ''
if (time > 0) {
time--
str = time + 's'
} else {
time = 60
str = '获取验证码'
}
that.time = time
that.codeTip = str
if (time == 60) {
clearInterval(id)
}
}, 1000)
},
//提交
gobind() {
if (!this.phoneStatus) this.$main.showToast('手机号格式有误,请重新输入')
var that = this
var params = {
phone: that.phone,
code: that.smsCode,
bindType: 2,
openId: that.userInfo.openId,
nickName: that.userInfo.nickName,
avatar: that.userInfo.avatar
}
bindWx(params, {
suc: res => {
util.showToast('登录成功')
var data = res.data;
uni.setStorageSync('token', data.token)
uni.setStorageSync('user', that.userInfo)
setTimeout(() => {
that.$path.reLaunch('/pages/index/home')
}, 1000)
}
})
},
//登录成功操作
loginSuccess(res) {
},
// 正则验证
getRegExp(value) {
let regExp =
/^1[3-9]\d{9}$/
if (regExp.test(value)) {
this.phoneStatus = true
} else {
this.phoneStatus = false
}
},
// 手机号输入框失焦事件
handleBlur (e) {
this.getRegExp(this.phone)
}
}
}
</script>
<style>
.white-content {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
background: white;
}
.logo {
width: 380rpx;
height: 120rpx;
margin-top: 170rpx;
}
.content {
width: calc(100% - 140rpx);
margin: 24rpx 70rpx 0 70rpx;
}
.input-row {
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
margin-top: 27rpx;
border-bottom: 2rpx solid #f2f2f2;
}
.input-row image {
width: 40rpx;
height: 40rpx;
}
.input-row label {
width: 120rpx;
font-size: 26rpx;
font-weight: bold;
color: #020202;
}
.input-row image:last-child {
height: 30rpx;
}
.input-row input {
flex: 1;
padding: 40rpx 26rpx;
height: auto;
font-size: 26rpx;
}
.input-row button {
padding: 0 24rpx;
min-width: 142rpx;
height: 50rpx;
line-height: 50rpx;
font-size: 20rpx;
color: #ff3c39;;
border-radius: 40rpx;
border: 1rpx solid #ff3c39;;
}
.input-row button[disabled] {
border: 1rpx solid #F2F2F2;
}
.agreement {
width: 100vw;
position: absolute;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
color: #AAAAAA;
font-size: 24rpx;
}
.agreement text {
color: #007AFF;
}
.input-tip {
display: flex;
color: #999999;
font-size: 24rpx;
margin-top: 10rpx;
}
</style>
<template>
<view class="cx-detail">
<!-- <view class="title" v-if="name">
{{name}}
</view> -->
<view class="detail" ref="detail" id="detail" v-html="detail"></view>
</view>
</template>
<script>
import {
contractDetail,
medicalWikiSecondDetail,
agreementDetail
} from '@/config/api.js'
export default {
data() {
return {
invateCode: this.invateCode,
type: null,
id: null,
name: null,
status: null,
detail: null,
imgSrc: ''
}
},
onLoad (options) {
Object.assign(this, this.$options.data())
wx.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
if (options.id) this.id = options.id
if (options.detail) this.detail = options.detail
if (options.status) this.status = options.status
if (options.title) {
this.$main.setNavigationBarTitle(options.title)
} else {
this.$main.setNavigationBarTitle('详情')
}
if (options.type) {
this.type = options.type
this.getApiagreementTips()
}
},
// 分享给朋友
onShareAppMessage (res) {
return {
title: '快来注册吧',
path: '/pages/index/home?invateCode=' + this.invateCode
}
},
// 分享朋友圈
onShareTimeline () {
return {
title: '快来注册吧',
query: '/pages/index/home?invateCode=' + this.invateCode
}
},
methods: {
// 协议、说明详情
getApiagreementTips () {
let that = this
let params = {
type: that.type
}
agreementDetail(params, {
suc: (res) => {
that.detail = res.data.detailHtml
}
})
}
}
}
</script>
<style scoped lang="less">
.title {
padding: 20rpx;
box-sizing: border-box;
color: #020202;
font-size: 32rpx;
text-align: center;
font-weight:bold;
background-color: #FFF;
}
.detail {
white-space: pre-wrap;
}
</style>
<template>
<view class="cx-login">
<view class="top-box">
<view class="view-bg">
</view>
<view class="wx-login-box">
<image class="icon" :src="imgBaseUrl + 'WeChatdl.png'" webp="true" lazy-load="true" :style="{'margin-bottom': authType ? '60rpx;' : '0'}"></image>
<button v-if="authType" class="button" style="background-color: #2EA9EA;" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权手机号</button>
<button v-else class="button" open-type="getUserInfo" @click="getWxLogin()">微信授权登录</button>
</view>
<view class="bottom-box">
<!-- <view class="text-box">
<p class="text">登录即表明同意</p>
<p class="agreement" @click="btnPath('./detail?type=4&status=2')">《台粮道用户协议》</p>
<p class="text"></p>
<p class="agreement" @click="btnPath('./detail?type=4&status=3')">《隐私政策》</p>
</view> -->
<p class="support">POWERED BY&copy;六方网络</p>
</view>
</view>
</view>
</template>
<script>
import util from '@/config/util.js'
import {
getId,
wxLogin,
bindWx,
personal,
checkCode
} from '@/config/api.js'
export default {
data() {
return {
imgBaseUrl: null,
userInfo: null,
openId: null,
codeText: '获取验证码',
passText: 'password',
invateCode: '',
phone: '',
jsonData: {},
authType: 0
}
},
onLoad() {
Object.assign(this, this.$options.data())
this.imgBaseUrl = this.$api.IMG_BASE_URL
if (this.$store.getStorageSync('invateCode')) {
this.invateCode = this.$store.getStorageSync('invateCode')
}
},
methods: {
// 获取验证码
getApiCode() {
setTimeout(() => {
if (!this.phoneValue) return this.$main.showToast('手机号不能为空!')
if (!this.phoneStatus) return this.$main.showToast('您输入的手机号有误,请重新输入')
let that = this
let num = 60
let params = {
phone: that.phoneValue
}
checkCode(params, {
suc: (res) => {
that.$main.showToast('验证码已发送')
let timeSmap = setInterval(function() {
num--
that.codeText = num + 's后重新获取'
if (!num) {
clearInterval(timeSmap)
that.codeText = '获取验证码'
}
}, 1000)
},
err: (err) => {
}
})
}, 50)
},
// 获取手机号
getPhoneNumber (e) {
this.getWxLogin(e.detail.encryptedData, e.detail.iv)
},
// 绑定微信
apiBind (data) {
console.log(1111, this.invateCode)
let that = this
let params = {
phone: data.phone,
bindType: 2,
openId: data.openId,
nickName: data.nickName,
avatar: data.avatar
}
if (that.invateCode) params.invitationCode = that.invateCode
bindWx(params, {
suc: (res) => {
that.$main.showToast('登录成功', 1000)
let token = res.data.tokenHead + ' ' + res.data.token
if (this.$store.getStorageSync('invateCode')) {
this.$store.removeStorageSync('invateCode')
}
uni.setStorageSync('token', token)
let userInfo = {
avatar: data.avatar,
phone: data.phone,
nickName: data.nickName
}
uni.setStorageSync('user', userInfo)
setTimeout(() => {
that.$path.reLaunch('/pages/index/home')
}, 1000)
}
})
},
// 微信登录
getWxLogin (data, iv) {
let that = this
wx.login({
success (res) {
if (that.authType) {
let params = {
jsCode: res.code,
encryptedData: data,
iv: iv
}
if (that.invateCode) params.invitationCode = that.invateCode
getId(params, {
suc: (ress) => {
let token = ress.data.tokenHead + ' ' + ress.data.token
that.$store.setStorageSync('token', token)
that.$main.showToast('登录成功', 1000)
setTimeout(() => {
that.$path.reLaunch('/pages/index/home')
}, 1000)
},
erc: (err) => {
if (err.data.code === 15000) {
that.phone = err.data.data.phone
that.jsonData.phone = that.phone
// let jsonData = {
// phone: that.phone,
// openId: err.data.data.openId,
// nickName: ress.userInfo.nickName,
// avatar: ress.userInfo.avatarUrl
// }
that.apiBind(that.jsonData)
}
}
})
} else {
wx.getUserInfo({
success: function(ress) {
that.$main.showLoading('登陆中')
let params = {
jsCode: res.code,
encryptedData: ress.encryptedData,
iv: ress.iv
}
if (that.invateCode) params.invitationCode = that.invateCode
getId(params, {
suc: (reslove) => {
that.$main.hideLoading()
let token = reslove.data.tokenHead + ' ' + reslove.data.token
that.$store.setStorageSync('token', token)
if (that.$store.getStorageSync('invateCode')) {
that.$store.removeStorageSync('invateCode')
}
that.$main.showToast('登录成功', 1000)
setTimeout(() => {
that.$path.reLaunch('/pages/index/home')
}, 1000)
},
erc: err => {
if (err.data.code === 15000) {
that.jsonData = {
openId: err.data.data.openid,
nickName: ress.userInfo.nickName,
avatar: ress.userInfo.avatarUrl
}
that.authType = 1
that.$forceUpdate()
// let jsonData = {
// phone: that.phone,
// openId: err.data.data.openId,
// nickName: ress.userInfo.nickName,
// avatar: ress.userInfo.avatarUrl
// }
// that.apiBind(jsonData)
}
}
})
},
fail: function(err) {
that.$main.hideLoading()
}
})
}
},
fail: (err) => {
}
})
},
// 获取个人信息
getApiUserInfo (status) {
let that = this
let params = ''
personal(params, {
suc: (res) => {
let data = res.data
if (status) {
uni.getUserInfo({
provider: 'weixin',
success: function (info) {
that.userInfo = {
nickName: info.userInfo.nickName,
avatar: info.userInfo.avatarUrl
}
data.nickName = info.userInfo.nickName
data.avatar = info.userInfo.avatarUrl
that.$store.setStorageSync('user', data)
}
})
} else {
that.$store.setStorageSync('user', data)
}
}
})
},
// 路由 - 跳转子页面
btnPath(url) {
this.$path.navigateTo(url)
}
}
}
</script>
<style>
</style>
<template>
<view class="cx-more">
<view class="imgs-box" v-if="type == 1">
<image class="img" v-for="(item, index) in imgList" :key="index" :src="item.pic" @click="btnPreviewImage(index, imgList)" mode="aspectFill"></image>
</view>
<view class="new-box" v-if="type == 2">
<view class="list" v-for="(item, index) in newsList" :key="index">
<p class="left">{{item.title}} | {{item.subTitle}}</p>
<p class="date">{{item.createDate.split(' ')[0]}}</p>
</view>
</view>
</view>
</template>
<script>
import {
tlImages,
tlNews
} from '@/config/api.js'
export default {
data() {
return {
invateCode: this.invateCode,
type: 0,
imgList: [],
newsList: [],
page: 1,
total: 0
}
},
onLoad (options) {
Object.assign(this, this.$options.data())
wx.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
this.type = options.type
this.getApiIndexData()
},
// 分享给朋友
onShareAppMessage (res) {
return {
title: '快来注册吧',
path: '/pages/index/home?invateCode=' + this.invateCode
}
},
// 分享朋友圈
onShareTimeline () {
return {
title: '快来注册吧',
query: '/pages/index/home?invateCode=' + this.invateCode
}
},
// 触底刷新
onReachBottom () {
if (!this.total) return
this.page++
if (this.type == 1) {
if (this.total === this.imgList.length) return
this.imgList = []
} else if (this.type == 2){
if (this.total === this.newsList.length) return
this.newsList = []
}
this.getApiIndexData()
},
methods: {
// 请求主数据
getApiIndexData () {
if (this.type == 1) {
let that = this
let params = {
pageNum: that.page,
pageSize: 30
}
tlImages(params, {
suc: (res) => {
that.total = res.data.total
if (res.data.pageNum === 1) that.imgList = []
that.imgList = that.imgList.concat(res.data.list)
}
})
} else {
let that = this
let params = {
pageNum: that.page,
pageSize: 30
}
tlNews(params, {
suc: (res) => {
that.total = res.data.total
if (res.data.pageNum === 1) that.newsList = []
that.newsList = that.newsList.concat(res.data.list)
}
})
}
},
// 查看大图
btnPreviewImage (index, imgs) {
let arr = []
for (let i = 0; i < imgs.length; i++) {
arr.push(imgs[i].pic)
}
uni.previewImage({
current: index,
urls: arr
})
},
}
}
</script>
<style>
</style>
<template>
<view class="cx-web-view">
<web-view :src="src"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
src: ''
}
},
onLoad (options) {
Object.assign(this, this.$options.data())
this.src = options.src
},
methods: {
}
}
</script>
<style>
</style>
<template>
<view class="cx-about-us">
<view class="logo-box">
<image class="logo" :src="imgBaseUrl + 'logowe.png'" webp="true" lazy-load="true"></image>
</view>
<view class="edition-info">{{mobileInfo}}</view>
<view class="option-box">
<view class="options">
<p class="title">邮箱</p>
<view class="right">
<p class="text">632598226@qq.com</p>
<image class="icon" :src="imgBaseUrl + 'page.png'" webp="true" lazy-load="true"></image>
</view>
</view>
<view class="options">
<p class="title">官方微信公众号</p>
<view class="right">
<p class="text">jsksjd</p>
<image class="icon" :src="imgBaseUrl + 'page.png'" webp="true" lazy-load="true"></image>
</view>
</view>
<view class="options">
<p class="title">官方微博</p>
<view class="right">
<p class="text">jsksjd</p>
<image class="icon" :src="imgBaseUrl + 'page.png'" webp="true" lazy-load="true"></image>
</view>
</view>
<view class="options">
<p class="title">官网技术支持</p>
<view class="right">
<p class="text">泉州六方网络有限公司</p>
<image class="icon" :src="imgBaseUrl + 'page.png'" webp="true" lazy-load="true"></image>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
Ok: false,
imgBaseUrl: null,
invateCode: this.invateCode,
mobileInfo: ''
}
},
onLoad () {
Object.assign(this, this.$options.data())
this.imgBaseUrl = this.$api.IMG_BASE_URL
wx.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
this.getSystemInfo()
},
// 分享给朋友
onShareAppMessage (res) {
return {
title: '快来注册吧',
path: '/pages/index/home?invateCode=' + this.invateCode
}
},
// 分享朋友圈
onShareTimeline () {
return {
title: '快来注册吧',
query: '/pages/index/home?invateCode=' + this.invateCode
}
},
methods: {
// 获取系统信息
getSystemInfo () {
uni.getSystemInfo({
success: res => {
let system = res.platform == 'ios' ? 'ios版本' : '安卓版本'
let edition = res.system.substr(res.system.indexOf(' '))
this.mobileInfo = system + edition
}
})
}
}
}
</script>
<style>
</style>
<template>
<view class="cx-balance-record">
<uni-nav-bar left-icon="back" title="余额明细" right-text=" " :fixed="true" :statusBar="true" :border="false" @clickLeft="btnBack(1)">
</uni-nav-bar>
<view class="tips-box">
<p>总支出:¥{{outcome}} &nbsp;&nbsp; 总收入:¥{{income}}</p>
<p @click="btnPath('/pages/index/detail?type=6')">说明</p>
</view>
<view class="record-box">
<view class="options" v-for="(item, index) in list" :key="index">
<view class="left-box">
<p class="title" v-if="item.type === 1">购买商品</p>
<p class="title" v-else-if="item.type === 2">下级升级获得</p>
<p class="title" v-else-if="item.type === 3">提现</p>
<p class="title" v-else-if="item.type === 5">佣金管理奖</p>
<p class="title" v-else-if="item.type === 6">直推佣金</p>
<p class="title" v-else-if="item.type === 7">间推佣金</p>
<p class="title" v-else-if="item.type === 8">管理奖转入</p>
<p class="title" v-else-if="item.type === 9">管理奖转出</p>
<view class="count red" v-if="item.changeType === 2">-{{item.changeAmount}}</view>
<view class="count black" v-else>+{{item.changeAmount}}</view>
</view>
<p class="time">{{item.createDate}}</p>
</view>
</view>
</view>
</template>
<script>
import {
balanceRecord
} from '@/config/api.js'
export default {
data() {
return {
invateCode: this.invateCode,
imgBaseUrl: null,
list: [],
income: 0,
outcome: 0,
page: 1,
total: 0
}
},
onLoad () {
Object.assign(this, this.$options.data())
this.imgBaseUrl = this.$api.IMG_BASE_URL
wx.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
this.getApiIndexData()
},
// 分享给朋友
onShareAppMessage (res) {
return {
title: '快来注册吧',
path: '/pages/index/home?invateCode=' + this.invateCode
}
},
// 分享朋友圈
onShareTimeline () {
return {
title: '快来注册吧',
query: '/pages/index/home?invateCode=' + this.invateCode
}
},
methods: {
// 获取主数据
getApiIndexData () {
let that = this
let params = {
pageNum: that.page,
pageSize: 15
}
balanceRecord(params, {
suc: (res) => {
that.total = res.data.detailList.total
if (res.data.detailList.pageNum === 1) that.list = []
that.list = that.list.concat(res.data.detailList.list)
that.outcome = res.data.allExpenditure
that.income = res.data.allIncome
}
})
},
// 路由 - 跳转子页面
btnPath (url) {
this.$path.navigateTo(url)
},
// 路由 - 回退
btnBack (count) {
this.$path.navigateBack(1)
}
},
// 触底刷新
onReachBottom () {
if (!this.total) return
if (this.total === this.list.length) return
this.page++
this.getApiIndexData()
}
}
</script>
<style scoped lang="less">
.record-box {
height: calc(100vh - 88rpx - 82rpx - var(--status-bar-height));
}
</style>
<template>
<view class="cx-cash-out">
<view class="top-tips">提现需要扣除手续费3%,到账时间以实际到账时间为准</view>
<view class="option-box">
<view class="options">
<p class="title">当前余额</p>
<p class="text">{{balance.balance}}</p>
</view>
<view class="options">
<p class="title">收款人</p>
<input class="input" type="text" v-model="nameValue" placeholder="请输入收款人姓名" />
</view>
<view class="options">
<view class="title">收款方式</view>
<view class="right">
<view class="list" @click="type = 0">
<view class="border">
<view class="point" v-if="type === 0"></view>
</view>
<p class="text">支付宝</p>
</view>
<view class="list" @click="type = 1">
<view class="border">
<view class="point" v-if="type === 1"></view>
</view>
<p class="text">微信</p>
</view>
</view>
</view>
<view class="options">
<p class="title">提现金额</p>
<input class="input" type="digit" v-model="moneyValue" placeholder="请输入提现金额" @input="handleInput" />
</view>
<view class="options">
<p class="title">实际到账金额</p>
<p class="text">{{actualAmount}}</p>
</view>
</view>
<view class="btn" @click="chooseImage()">上传收款码</view>
<view class="btn" style="margin-top: 30rpx;" @click="btnSure()">确认提现,48小时内到账</view>
</view>
</template>
<script>
import {
cashOut,
ossPolicy,
myWallet,
} from '@/config/api.js'
export default {
data() {
return {
invateCode: this.invateCode,
type: 0,
balance: '',
nameValue: '',
moneyValue: '',
actualAmount: '',
imgURL: '',
openRequest: true // 按钮保护
}
},
onLoad () {
Object.assign(this, this.$options.data())
wx.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
this.getApiMoney()
},
// 分享给朋友
onShareAppMessage (res) {
return {
title: '快来注册吧',
path: '/pages/index/home?invateCode=' + this.invateCode
}
},
// 分享朋友圈
onShareTimeline () {
return {
title: '快来注册吧',
query: '/pages/index/home?invateCode=' + this.invateCode
}
},
methods: {
// 获取余额
getApiMoney () {
let that = this
myWallet('', {
suc: (res) => {
that.balance = res.data
}
})
},
// 提现按钮
btnSure () {
if (!this.openRequest) return
this.openRequest = false
if (!this.nameValue) {
this.openRequest = true
return this.$main.showToast('请输入收款人姓名!')
}
if (!this.moneyValue || this.moneyValue <= 0) {
this.openRequest = true
return this.$main.showToast('请输入提现金额!')
}
if (!this.imgURL) {
this.openRequest = true
return this.$main.showToast('请先上传收款码')
}
this.getApiCashOut()
},
// 选择图片操作
async chooseImage () {
let that = this
await uni.chooseImage({
count: 1,
success: res => {
for (let i = 0; i < res.tempFiles.length; i++) {
if (res.tempFiles[i].size > 2097152) return that.$main.showToast('您上传的图片过大,请重新上传')
that.getUpload(res.tempFiles[i].path)
}
},
fail: err => {
that.openRequest = true
}
})
},
// 上传
getUpload (data) {
let that = this
ossPolicy('', {
suc: (res) => {
let tiemr = new Date()
let address = res.data.dir + '/'
let str = data.substr(data.lastIndexOf('.'))
let nameStr = address + tiemr.getTime() + str
uni.uploadFile({
url: res.data.host,
filePath: data,
fileType: 'image',
name: 'file',
formData: {
name: nameStr,
key: nameStr,
policy: res.data.policy,
OSSAccessKeyId: res.data.accessKeyId,
success_action_status: '200',
signature: res.data.signature
},
success: ress => {
if (ress.statusCode == '200'){
// console.log(111, res.data.host + '/' + nameStr)
that.$main.showToast('上传成功')
let path = res.data.host + '/' + nameStr
that.imgURL = path
} else {
that.$main.showToast('上传失败,请重试')
}
}
})
}
})
},
// 提现接口
getApiCashOut () {
let that = this
let params = {
name: that.nameValue,
method: that.type,
amount: that.moneyValue,
withdrawalQrCode: that.imgURL
}
cashOut(params, {
suc: (res) => {
that.openRequest = true
that.$main.showToast('提现成功')
that.moneyValue = ''
that.nameValue = ''
that.imgURL = ''
that.actualAmount = ''
},
erc: (err) => {
that.openRequest = true
}
})
},
// 提现金额输入框事件
handleInput (e) {
if (!this.balance.balance || this.balance.balance === 0) {
this.$main.showToast('余额不足')
return this.actualAmount = ''
}
if (!e.detail.value) return this.actualAmount = ''
let value = e.detail.value
let count = value * 0.03
this.actualAmount = value - count
},
// 判断提现金额
getApiJudgAmount (value, id, type) {
let that = this
let params = {
withdrawalAmount: value,
userId: id,
userType: type
}
judgAmount(params, {
suc: (res) => {
that.openCashout = false
}
})
},
// 路由 - 跳转子页面
btnPath (url) {
this.$path.navigateTo(url)
},
// 路由 - 回退
btnBack (count) {
this.$path.navigateBack(count)
},
// 提现金额输入框失焦
handleBlur (e) {
setTimeout(() => {
// if (e.mp.detail.value > this.balance) return this.$main.showToast('提现金额超过可用金额!')
if (e.mp.detail.value) this.getApiJudgAmount(e.mp.detail.value, this.$store.getStorageSync('user').memberId, 1)
}, 50)
}
}
}
</script>
<style>
</style>
This diff is collapsed. Click to expand it.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment