feat: 初始化版本!
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<view class="upload">
|
||||
<view class="imagebox">
|
||||
<view class="imageborder">
|
||||
<view class="main">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="text">
|
||||
<text>{{ text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const text = ref("")
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.upload {
|
||||
height: 400rpx;
|
||||
width: 90%;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.imagebox {
|
||||
height: 80%;
|
||||
background-color: #eff8ff;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
|
||||
.imageborder {
|
||||
border: 5px #319fea solid;
|
||||
position: relative;
|
||||
width: 70%;
|
||||
height: 80%;
|
||||
border-radius: 30rpx;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
background-color: #eff8ff;
|
||||
height: 80%;
|
||||
width: 120%;
|
||||
top: 10%;
|
||||
left: -10%;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
background-color: #eff8ff;
|
||||
top: -10%;
|
||||
left: 10%;
|
||||
height: 120%;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.main {
|
||||
position: absolute;
|
||||
background-color: #eff8ff;
|
||||
top: 5%;
|
||||
left: 5%;
|
||||
height: 90%;
|
||||
width: 90%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
height: 20%;
|
||||
background-color: #319fea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,681 @@
|
||||
<template>
|
||||
<view v-show="show" class="t-wrapper" @touchmove.stop.prevent="moveHandle">
|
||||
<view class="t-mask" :class="{ active: active }" @click.stop="close"></view>
|
||||
<view class="t-box" :class="{ active: active }">
|
||||
<view class="t-header">
|
||||
<view class="t-header-button" @click="close">取消</view>
|
||||
<view class="t-header-button confrim" @click="confirm">确认</view>
|
||||
</view>
|
||||
<view class="t-color__box"
|
||||
:style="{ background: 'rgb(' + bgcolor.r + ',' + bgcolor.g + ',' + bgcolor.b + ')' }">
|
||||
<view class="t-background boxs" @touchstart="touchstart($event, 0)" @touchmove="touchmove($event, 0)"
|
||||
@touchend="touchend($event, 0)">
|
||||
<view class="t-color-mask"></view>
|
||||
<view class="t-pointer" :style="{ top: site[0].top - 8 + 'px', left: site[0].left - 8 + 'px' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-control__box">
|
||||
<view class="t-control__color">
|
||||
<view class="t-control__color-content"
|
||||
:style="{ background: 'rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a + ')' }"></view>
|
||||
</view>
|
||||
<view class="t-control-box__item">
|
||||
<view class="t-controller boxs" @touchstart="touchstart($event, 1)" @touchmove="touchmove($event, 1)"
|
||||
@touchend="touchend($event, 1)">
|
||||
<view class="t-hue">
|
||||
<view class="t-circle" :style="{ left: site[1].left - 12 + 'px' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-controller boxs" @touchstart="touchstart($event, 2)" @touchmove="touchmove($event, 2)"
|
||||
@touchend="touchend($event, 2)">
|
||||
<view class="t-transparency">
|
||||
<view class="t-circle" :style="{ left: site[2].left - 12 + 'px' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-result__box">
|
||||
<view v-if="mode" class="t-result__item">
|
||||
<view class="t-result__box-input">{{ hex }}</view>
|
||||
<view class="t-result__box-text">HEX</view>
|
||||
</view>
|
||||
<template v-else>
|
||||
<view class="t-result__item">
|
||||
<view class="t-result__box-input">{{ rgba.r }}</view>
|
||||
<view class="t-result__box-text">R</view>
|
||||
</view>
|
||||
<view class="t-result__item">
|
||||
<view class="t-result__box-input">{{ rgba.g }}</view>
|
||||
<view class="t-result__box-text">G</view>
|
||||
</view>
|
||||
<view class="t-result__item">
|
||||
<view class="t-result__box-input">{{ rgba.b }}</view>
|
||||
<view class="t-result__box-text">B</view>
|
||||
</view>
|
||||
<view class="t-result__item">
|
||||
<view class="t-result__box-input">{{ rgba.a }}</view>
|
||||
<view class="t-result__box-text">A</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view class="t-result__item t-select" @click="select">
|
||||
<view class="t-result__box-input">
|
||||
<view>切换</view>
|
||||
<view>模式</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-alternative">
|
||||
<view class="t-alternative__item" v-for="(item, index) in colorList" :key="index">
|
||||
<view class="t-alternative__item-content"
|
||||
:style="{ background: 'rgba(' + item.r + ',' + item.g + ',' + item.b + ',' + item.a + ')' }"
|
||||
@click="selectColor(item)">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { r: 0, g: 0, b: 0, a: 0 }
|
||||
}
|
||||
},
|
||||
spareColor: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
active: false,
|
||||
// rgba 颜色
|
||||
rgba: { r: 0, g: 0, b: 0, a: 1 },
|
||||
// hsb 颜色
|
||||
hsb: { h: 0, s: 0, b: 0 },
|
||||
site: [{ top: 0, left: 0 }, { left: 0 }, { left: 0 }],
|
||||
index: 0,
|
||||
bgcolor: { r: 255, g: 0, b: 0, a: 1 },
|
||||
hex: '#000000',
|
||||
mode: true,
|
||||
colorList: [
|
||||
{ r: 244, g: 67, b: 54, a: 1 },
|
||||
{ r: 233, g: 30, b: 99, a: 1 },
|
||||
{ r: 156, g: 39, b: 176, a: 1 },
|
||||
{ r: 103, g: 58, b: 183, a: 1 },
|
||||
{ r: 63, g: 81, b: 181, a: 1 },
|
||||
{ r: 33, g: 150, b: 243, a: 1 },
|
||||
{ r: 3, g: 169, b: 244, a: 1 },
|
||||
{ r: 0, g: 188, b: 212, a: 1 },
|
||||
{ r: 0, g: 150, b: 136, a: 1 },
|
||||
{ r: 76, g: 175, b: 80, a: 1 },
|
||||
{ r: 139, g: 195, b: 74, a: 1 },
|
||||
{ r: 205, g: 220, b: 57, a: 1 },
|
||||
{ r: 255, g: 235, b: 59, a: 1 },
|
||||
{ r: 255, g: 193, b: 7, a: 1 },
|
||||
{ r: 255, g: 152, b: 0, a: 1 },
|
||||
{ r: 255, g: 87, b: 34, a: 1 },
|
||||
{ r: 121, g: 85, b: 72, a: 1 },
|
||||
{ r: 158, g: 158, b: 158, a: 1 },
|
||||
{ r: 0, g: 0, b: 0, a: 0.5 },
|
||||
{ r: 0, g: 0, b: 0, a: 0 },
|
||||
]
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.rgba = this.color;
|
||||
if (this.spareColor.length !== 0) {
|
||||
this.colorList = this.spareColor;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init() {
|
||||
// hsb 颜色
|
||||
this.hsb = this.rgbToHex(this.rgba);
|
||||
this.setValue(this.rgba);
|
||||
},
|
||||
moveHandle() { },
|
||||
open() {
|
||||
this.show = true;
|
||||
this.$nextTick(() => {
|
||||
this.init();
|
||||
setTimeout(() => {
|
||||
this.active = true;
|
||||
setTimeout(() => {
|
||||
this.getSelectorQuery();
|
||||
}, 350)
|
||||
}, 50)
|
||||
})
|
||||
|
||||
},
|
||||
close() {
|
||||
this.active = false;
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.show = false;
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
confirm() {
|
||||
this.close();
|
||||
this.$emit('confirm', {
|
||||
rgba: this.rgba,
|
||||
hex: this.hex
|
||||
})
|
||||
},
|
||||
// 选择模式
|
||||
select() {
|
||||
this.mode = !this.mode
|
||||
},
|
||||
// 常用颜色选择
|
||||
selectColor(item) {
|
||||
this.setColorBySelect(item)
|
||||
},
|
||||
touchstart(e, index) {
|
||||
const { pageX, pageY, clientX, clientY } = e.touches[0];
|
||||
this.pageX = clientX;
|
||||
this.pageY = clientY;
|
||||
this.setPosition(this.pageX, this.pageY, index);
|
||||
},
|
||||
touchmove(e, index) {
|
||||
const { pageX, pageY, clientX, clientY } = e.touches[0];
|
||||
this.moveX = clientX;
|
||||
this.moveY = clientY;
|
||||
this.setPosition(this.moveX, this.moveY, index);
|
||||
},
|
||||
touchend(e, index) {
|
||||
},
|
||||
/**
|
||||
* 设置位置
|
||||
*/
|
||||
setPosition(x, y, index) {
|
||||
this.index = index;
|
||||
const {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height
|
||||
} = this.position[index];
|
||||
// 设置最大最小值
|
||||
|
||||
this.site[index].left = Math.max(0, Math.min(parseInt(x - left), width));
|
||||
if (index === 0) {
|
||||
this.site[index].top = Math.max(0, Math.min(parseInt(y - top), height));
|
||||
// 设置颜色
|
||||
this.hsb.s = parseInt((100 * this.site[index].left) / width);
|
||||
this.hsb.b = parseInt(100 - (100 * this.site[index].top) / height);
|
||||
this.setColor();
|
||||
this.setValue(this.rgba);
|
||||
} else {
|
||||
this.setControl(index, this.site[index].left);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 设置 rgb 颜色
|
||||
*/
|
||||
setColor() {
|
||||
const rgb = this.HSBToRGB(this.hsb);
|
||||
this.rgba.r = rgb.r;
|
||||
this.rgba.g = rgb.g;
|
||||
this.rgba.b = rgb.b;
|
||||
},
|
||||
/**
|
||||
* 设置二进制颜色
|
||||
* @param {Object} rgb
|
||||
*/
|
||||
setValue(rgb) {
|
||||
this.hex = '#' + this.rgbToHex(rgb);
|
||||
},
|
||||
setControl(index, x) {
|
||||
const {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height
|
||||
} = this.position[index];
|
||||
|
||||
if (index === 1) {
|
||||
this.hsb.h = parseInt((360 * x) / width);
|
||||
this.bgcolor = this.HSBToRGB({
|
||||
h: this.hsb.h,
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
this.setColor()
|
||||
} else {
|
||||
this.rgba.a = (x / width).toFixed(1);
|
||||
}
|
||||
this.setValue(this.rgba);
|
||||
},
|
||||
/**
|
||||
* rgb 转 二进制 hex
|
||||
* @param {Object} rgb
|
||||
*/
|
||||
rgbToHex(rgb) {
|
||||
let hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
|
||||
hex.map(function (str, i) {
|
||||
if (str.length == 1) {
|
||||
hex[i] = '0' + str;
|
||||
}
|
||||
});
|
||||
return hex.join('');
|
||||
},
|
||||
setColorBySelect(getrgb) {
|
||||
const {
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
a
|
||||
} = getrgb;
|
||||
let rgb = {}
|
||||
rgb = {
|
||||
r: r ? parseInt(r) : 0,
|
||||
g: g ? parseInt(g) : 0,
|
||||
b: b ? parseInt(b) : 0,
|
||||
a: a ? a : 0,
|
||||
};
|
||||
this.rgba = rgb;
|
||||
this.hsb = this.rgbToHsb(rgb);
|
||||
this.changeViewByHsb();
|
||||
},
|
||||
changeViewByHsb() {
|
||||
const [a, b, c] = this.position;
|
||||
this.site[0].left = parseInt(this.hsb.s * a.width / 100);
|
||||
this.site[0].top = parseInt((100 - this.hsb.b) * a.height / 100);
|
||||
this.setColor(this.hsb.h);
|
||||
this.setValue(this.rgba);
|
||||
this.bgcolor = this.HSBToRGB({
|
||||
h: this.hsb.h,
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
|
||||
this.site[1].left = this.hsb.h / 360 * b.width;
|
||||
this.site[2].left = this.rgba.a * c.width;
|
||||
|
||||
},
|
||||
/**
|
||||
* hsb 转 rgb
|
||||
* @param {Object} 颜色模式 H(hues)表示色相,S(saturation)表示饱和度,B(brightness)表示亮度
|
||||
*/
|
||||
HSBToRGB(hsb) {
|
||||
let rgb = {};
|
||||
let h = Math.round(hsb.h);
|
||||
let s = Math.round((hsb.s * 255) / 100);
|
||||
let v = Math.round((hsb.b * 255) / 100);
|
||||
if (s == 0) {
|
||||
rgb.r = rgb.g = rgb.b = v;
|
||||
} else {
|
||||
let t1 = v;
|
||||
let t2 = ((255 - s) * v) / 255;
|
||||
let t3 = ((t1 - t2) * (h % 60)) / 60;
|
||||
if (h == 360) h = 0;
|
||||
if (h < 60) {
|
||||
rgb.r = t1;
|
||||
rgb.b = t2;
|
||||
rgb.g = t2 + t3;
|
||||
} else if (h < 120) {
|
||||
rgb.g = t1;
|
||||
rgb.b = t2;
|
||||
rgb.r = t1 - t3;
|
||||
} else if (h < 180) {
|
||||
rgb.g = t1;
|
||||
rgb.r = t2;
|
||||
rgb.b = t2 + t3;
|
||||
} else if (h < 240) {
|
||||
rgb.b = t1;
|
||||
rgb.r = t2;
|
||||
rgb.g = t1 - t3;
|
||||
} else if (h < 300) {
|
||||
rgb.b = t1;
|
||||
rgb.g = t2;
|
||||
rgb.r = t2 + t3;
|
||||
} else if (h < 360) {
|
||||
rgb.r = t1;
|
||||
rgb.g = t2;
|
||||
rgb.b = t1 - t3;
|
||||
} else {
|
||||
rgb.r = 0;
|
||||
rgb.g = 0;
|
||||
rgb.b = 0;
|
||||
}
|
||||
}
|
||||
return {
|
||||
r: Math.round(rgb.r),
|
||||
g: Math.round(rgb.g),
|
||||
b: Math.round(rgb.b)
|
||||
};
|
||||
},
|
||||
rgbToHsb(rgb) {
|
||||
let hsb = {
|
||||
h: 0,
|
||||
s: 0,
|
||||
b: 0
|
||||
};
|
||||
let min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||
let max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||
let delta = max - min;
|
||||
hsb.b = max;
|
||||
hsb.s = max != 0 ? 255 * delta / max : 0;
|
||||
if (hsb.s != 0) {
|
||||
if (rgb.r == max) hsb.h = (rgb.g - rgb.b) / delta;
|
||||
else if (rgb.g == max) hsb.h = 2 + (rgb.b - rgb.r) / delta;
|
||||
else hsb.h = 4 + (rgb.r - rgb.g) / delta;
|
||||
} else hsb.h = -1;
|
||||
hsb.h *= 60;
|
||||
if (hsb.h < 0) hsb.h = 0;
|
||||
hsb.s *= 100 / 255;
|
||||
hsb.b *= 100 / 255;
|
||||
return hsb;
|
||||
},
|
||||
getSelectorQuery() {
|
||||
const views = uni.createSelectorQuery().in(this);
|
||||
views
|
||||
.selectAll('.boxs')
|
||||
.boundingClientRect(data => {
|
||||
if (!data || data.length === 0) {
|
||||
setTimeout(() => this.getSelectorQuery(), 20)
|
||||
return
|
||||
}
|
||||
this.position = data;
|
||||
// this.site[0].top = data[0].height;
|
||||
// this.site[0].left = 0;
|
||||
// this.site[1].left = data[1].width;
|
||||
// this.site[2].left = data[2].width;
|
||||
this.setColorBySelect(this.rgba);
|
||||
})
|
||||
.exec();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
spareColor(newVal) {
|
||||
this.colorList = newVal;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.t-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.t-box {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
padding: 30upx 0;
|
||||
padding-top: 0;
|
||||
background: #fff;
|
||||
transition: all 0.3s;
|
||||
transform: translateY(100%);
|
||||
|
||||
&.active {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
|
||||
.t-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 100upx;
|
||||
border-bottom: 1px #eee solid;
|
||||
box-shadow: 1px 0 2px rgba(0, 0, 0, 0.1);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.t-header-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 150upx;
|
||||
height: 100upx;
|
||||
font-size: 30upx;
|
||||
color: #666;
|
||||
padding-left: 20upx;
|
||||
|
||||
&:last-child {
|
||||
justify-content: flex-end;
|
||||
padding-right: 20upx;
|
||||
}
|
||||
|
||||
&.confrim {
|
||||
color: #007AFF;
|
||||
}
|
||||
}
|
||||
|
||||
.t-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
z-index: -1;
|
||||
transition: all 0.3s;
|
||||
opacity: 0;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.t-color__box {
|
||||
position: relative;
|
||||
height: 400upx;
|
||||
background: rgb(255, 0, 0);
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
margin: 0 20upx;
|
||||
margin-top: 20upx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.t-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.t-color-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 400upx;
|
||||
background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
.t-pointer {
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
left: -8px;
|
||||
z-index: 2;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border: 1px #fff solid;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.t-show-color {
|
||||
width: 100upx;
|
||||
height: 50upx;
|
||||
}
|
||||
|
||||
.t-control__box {
|
||||
margin-top: 50upx;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding-left: 20upx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.t-control__color {
|
||||
flex-shrink: 0;
|
||||
width: 100upx;
|
||||
height: 100upx;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
|
||||
linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
|
||||
background-size: 36upx 36upx;
|
||||
background-position: 0 0, 18upx 18upx;
|
||||
border: 1px #eee solid;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.t-control__color-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.t-control-box__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0 30upx;
|
||||
}
|
||||
|
||||
.t-controller {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
background-color: #fff;
|
||||
background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
|
||||
linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
|
||||
background-size: 32upx 32upx;
|
||||
background-position: 0 0, 16upx 16upx;
|
||||
}
|
||||
|
||||
.t-hue {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
|
||||
}
|
||||
|
||||
.t-transparency {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0));
|
||||
}
|
||||
|
||||
.t-circle {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.t-result__box {
|
||||
margin-top: 20upx;
|
||||
padding: 10upx;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.t-result__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10upx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.t-result__box-input {
|
||||
padding: 10upx 0;
|
||||
width: 100%;
|
||||
font-size: 28upx;
|
||||
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||
color: #999;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.t-result__box-text {
|
||||
margin-top: 10upx;
|
||||
font-size: 28upx;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.t-select {
|
||||
flex-shrink: 0;
|
||||
width: 150upx;
|
||||
padding: 0 30upx;
|
||||
|
||||
.t-result__box-input {
|
||||
border-radius: 10upx;
|
||||
border: none;
|
||||
color: #999;
|
||||
box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.1);
|
||||
background: #fff;
|
||||
|
||||
&:active {
|
||||
box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.t-alternative {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
padding-right: 10upx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.t-alternative__item {
|
||||
margin-left: 12upx;
|
||||
margin-top: 10upx;
|
||||
width: 50upx;
|
||||
height: 50upx;
|
||||
border-radius: 10upx;
|
||||
background-color: #fff;
|
||||
background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
|
||||
linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
|
||||
background-size: 36upx 36upx;
|
||||
background-position: 0 0, 18upx 18upx;
|
||||
border: 1px #eee solid;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transition: all 0.3s;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
.t-alternative__item-content {
|
||||
width: 50upx;
|
||||
height: 50upx;
|
||||
background: rgba(255, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<view class="card" :class="type" @click="$emit('click')">
|
||||
<image class="img" :src="img"/>
|
||||
<view class="right">
|
||||
<view class="title">{{ title }}</view>
|
||||
<view class="subTitle">{{ subTitle }}</view>
|
||||
<view class="price">¥ {{ price }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
img: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'line'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card {
|
||||
padding: 0;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
height: 240rpx;
|
||||
width: 700rpx;
|
||||
padding: 20rpx;
|
||||
margin: 10rpx;
|
||||
position: relative;
|
||||
|
||||
.img {
|
||||
height: 200rpx;
|
||||
width: 200rpx;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 240rpx;
|
||||
height: 200rpx;
|
||||
|
||||
.title {
|
||||
width: 400rpx;
|
||||
font-size: 35rpx;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
width: 400rpx;
|
||||
margin-top: 10rpx;
|
||||
font-size: 20rpx;
|
||||
color: rgb(87, 87, 87);
|
||||
}
|
||||
|
||||
.price {
|
||||
position: absolute;
|
||||
font-size: 40rpx;
|
||||
color: red;
|
||||
bottom: 10rpx;
|
||||
width: 400rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rect {
|
||||
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
height: 500rpx;
|
||||
width: 350rpx;
|
||||
padding: 0px;
|
||||
margin: 10rpx;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
.img {
|
||||
border-radius: 10px 10px 0 0;
|
||||
height: 350rpx;
|
||||
width: 350rpx;
|
||||
}
|
||||
|
||||
.right {
|
||||
padding: 20rpx;
|
||||
position: absolute;
|
||||
height: 160rpx;
|
||||
width: 350rpx;
|
||||
top: 350rpx;
|
||||
left: 20rpx;
|
||||
.title {
|
||||
width: 330rpx;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
width: 330rpx;
|
||||
margin-top: 10rpx;
|
||||
font-size: 20rpx;
|
||||
color: rgb(87, 87, 87);
|
||||
}
|
||||
|
||||
.price {
|
||||
position: absolute;
|
||||
font-size: 30rpx;
|
||||
color: red;
|
||||
bottom: 10rpx;
|
||||
width: 330rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
82
src/components/geek-xd/components/geek-menu/geek-menu.vue
Normal file
82
src/components/geek-xd/components/geek-menu/geek-menu.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<view class="menu" :class="type" :style="menuStyle" @click="$emit('click')">
|
||||
<image :src="icon" :style="imageStyle"></image>
|
||||
</view>
|
||||
<view class="title" :style="titleStype">{{ label }}</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 80
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: "菜单"
|
||||
},
|
||||
labelColor: {
|
||||
type: String,
|
||||
default: '#515151'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'circle'
|
||||
}
|
||||
})
|
||||
const menuStyle = computed(() => {
|
||||
return {
|
||||
width: `${props.size + 40}rpx`,
|
||||
height: `${props.size + 40}rpx`
|
||||
}
|
||||
})
|
||||
|
||||
const imageStyle = computed(() => {
|
||||
return {
|
||||
width: `${props.size + (props.type === 'rect' ? 20 : 0)}rpx`,
|
||||
height: `${props.size + (props.type === 'rect' ? 20 : 0)}rpx`
|
||||
}
|
||||
})
|
||||
|
||||
const titleStype = computed(() => {
|
||||
return {
|
||||
width: `${props.size + 40}rpx`,
|
||||
color: props.labelColor
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.circle {
|
||||
padding: 20rpx;
|
||||
border-radius: 10000px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
|
||||
&:active {
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.rect {
|
||||
padding: 0rpx;
|
||||
|
||||
&:active {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
229
src/components/geek-xd/components/geek-order/geek-order.vue
Normal file
229
src/components/geek-xd/components/geek-order/geek-order.vue
Normal file
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<view class="geek-card" @click="$emit('click')">
|
||||
<view class="geek-header">
|
||||
<view class="geek-shop">{{ shop }} > </view>
|
||||
<view class="geek-status">{{ status }}</view>
|
||||
</view>
|
||||
<view class="geek-content">
|
||||
<image class="geek-img" :src="img"></image>
|
||||
<view class="geek-label">{{ label }}</view>
|
||||
<view class="geek-sum">
|
||||
<view class=".geek-sum-1">¥{{ number.integerPart }}</view>
|
||||
<view class=".geek-sum-2">. {{ number.decimalPart }}</view>
|
||||
<view class=".geek-sum-3">共 {{ num }} 件</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="geek-footer">
|
||||
<view class="geek-more" @click="$emit('more')">更多</view>
|
||||
<view class="geek-buttonGroup">
|
||||
<view class="geek-btn" @click="$emit('sell')">卖了换钱</view>
|
||||
<view class="geek-btn" @click="$emit('return')">退换/售后</view>
|
||||
<view class="geek-buy" @click="$emit('again')">再次购买</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
shop: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
img: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
num: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'line'
|
||||
}
|
||||
})
|
||||
|
||||
const number = computed(() => {
|
||||
return formatNumber(props.price, 2)
|
||||
})
|
||||
|
||||
function formatNumber(num, place) {
|
||||
|
||||
let fixedNum = Number(num).toFixed(place); // 将数字保留两位小数
|
||||
let parts = fixedNum.split('.'); // 拆分整数部分和小数部分
|
||||
let integerPart = parts[0]; // 整数部分
|
||||
let decimalPart = parts[1]; // 小数部分
|
||||
|
||||
// 使用padStart方法补0到小数部分
|
||||
decimalPart = decimalPart.padStart(place, '0');
|
||||
|
||||
return {
|
||||
integerPart, decimalPart
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.geek-card {
|
||||
|
||||
position: relative;
|
||||
padding: 28rpx 18rpx 26rpx 16rpx;
|
||||
border: 1rpx solid rgb(183, 183, 183);
|
||||
border-radius: 50rpx;
|
||||
height: 400rpx;
|
||||
width: 700rpx;
|
||||
margin: 25rpx;
|
||||
|
||||
.geek-header {
|
||||
height: 60rpx;
|
||||
width: 664rpx;
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
.geek-shop {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.geek-status {
|
||||
width: 100rpx;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
opacity: 0.5;
|
||||
top: 30rpx;
|
||||
right: 30rpx;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.geek-content {
|
||||
position: relative;
|
||||
|
||||
margin-bottom: 46rpx;
|
||||
height: 170rpx;
|
||||
width: 664rpx;
|
||||
|
||||
.geek-img {
|
||||
border-radius: 30rpx;
|
||||
height: 170rpx;
|
||||
width: 170rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.geek-label {
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
left: 178rpx;
|
||||
|
||||
width: 350rpx;
|
||||
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.geek-sum {
|
||||
position: absolute;
|
||||
top: 44rpx;
|
||||
right: 0rpx;
|
||||
|
||||
width: 126rpx;
|
||||
height: 84rpx;
|
||||
|
||||
.geek-sum-1 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.geek-sum-2 {
|
||||
position: absolute;
|
||||
top: 30rpx;
|
||||
left: 84rpx;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.geek-sum-3 {
|
||||
position: absolute;
|
||||
top: 55rpx;
|
||||
left: 46rpx;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.geek-footer {
|
||||
height: 60rpx;
|
||||
width: 664rpx;
|
||||
font-size: 25rpx;
|
||||
|
||||
.geek-more {
|
||||
width: 100rpx;
|
||||
height: 60rpx;
|
||||
margin-right: 110rpx;
|
||||
|
||||
padding: 10rpx;
|
||||
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.geek-buttonGroup {
|
||||
width: 450rpx;
|
||||
height: 60rpx;
|
||||
display: inline-block;
|
||||
|
||||
.geek-btn {
|
||||
border: 1rpx solid #E9E9E9;
|
||||
width: 140rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 80rpx;
|
||||
opacity: 0.8;
|
||||
|
||||
padding: 10rpx;
|
||||
|
||||
margin-right: 10rpx;
|
||||
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
|
||||
.geek-buy {
|
||||
width: 140rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 80rpx;
|
||||
opacity: 0.8;
|
||||
|
||||
padding: 10rpx;
|
||||
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
|
||||
color: #F25E53;
|
||||
border: 1rpx solid #F4DADA;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
90
src/components/geek-xd/components/geek-qrcode/README.md
Normal file
90
src/components/geek-xd/components/geek-qrcode/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# uni-app 二维码生成器
|
||||
|
||||
改自作者诗小柒的tki-qrcode二维码生成器
|
||||
|
||||
### 作者:董玉可
|
||||
|
||||
1. H5、微信小程序、支付宝小程序、APP,其它平台的小程序没有测试
|
||||
2. 使用canvas生成
|
||||
3. 可设置二维码背景色,前景色,角标色
|
||||
4. 可设置二维码logo
|
||||
|
||||
## 重要的事情说3遍 重要的事情说3遍 重要的事情说3遍
|
||||
|
||||
1. IOS、Android真机都可以正常生成二维码
|
||||
2. 使用的时候出现无法生成二维码或空白的请先github直接打包下载,问题依旧,请github上直接提出问题并配图
|
||||
3. 有问题请说明问题原因,这样我才好定位,否则我也无法解决
|
||||
4. 如果此插件有帮助到你请打5分或赞赏我,你的支持是我更新的动力
|
||||
|
||||
+ 图片1 是微信小程序真机实测
|
||||
+ 图片2 是微信小程序模拟实测
|
||||
+ 图片3 是支付宝小程序模拟器实测
|
||||
+ 图片4 是安卓真机实测
|
||||
+ 图片5 H5
|
||||
|
||||
### 使用方法
|
||||
|
||||
在 `template` 中使用
|
||||
|
||||
```javascript
|
||||
<view class="qrimg">
|
||||
<geek-qrcode
|
||||
ref="qrcode"
|
||||
:cid="cid"
|
||||
:val="val"
|
||||
:size="size"
|
||||
:unit="unit"
|
||||
:background="background"
|
||||
:foreground="foreground"
|
||||
:pdground="pdground"
|
||||
:icon="icon"
|
||||
:iconSize="iconsize"
|
||||
:lv="lv"
|
||||
:onval="onval"
|
||||
:loadMake="loadMake"
|
||||
:usingComponents="usingComponents"
|
||||
:showLoading="showLoading"
|
||||
:loadingText="loadingText"
|
||||
@result="qrR" />
|
||||
</view>
|
||||
```
|
||||
|
||||
### 属性
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 可选值 | 说明 |
|
||||
| :-------------- | :-----: | :---------------: | :----: | :-------------------------------------------------------------------------------------------------- |
|
||||
| cid | String | tki-qrcode-canvas | | canvasId,页面存在多个二维码组件时需设置不同的ID |
|
||||
| size | Number | 200 | | 生成的二维码大小 |
|
||||
| unit | String | upx | px | 大小单位尺寸 |
|
||||
| show | Boolean | true | | 默认使用组件中的image标签显示二维码 |
|
||||
| val | String | 二维码 | | 要生成的内容 |
|
||||
| background | String | #000000 | | 二维码背景色 |
|
||||
| foreground | String | #ffffff | | 二维码前景色 |
|
||||
| pdground | String | #ffffff | | 二维码角标色 |
|
||||
| icon | String | | | 二维码图标URL(必须是本地图片,网络图需要先下载至本地) |
|
||||
| iconSize | Number | 40 | | 二维码图标大小(注意此大小不会跟随二维码size 动态变化,设置时需要注意大小,不要太大,以免无法识别) |
|
||||
| lv | Number | 3 | | 容错级别(一般不用设置) |
|
||||
| onval | Boolean | false | | 监听val值变化自动重新生成二维码 |
|
||||
| loadMake | Boolean | false | | 组件初始化完成后自动生成二维码,val需要有值 |
|
||||
| usingComponents | Boolean | true | false | 是否使用了自定义组件模式(主要是为了修复非自定义组件模式时 v-if 无法生成二维码的问题) |
|
||||
| showLoading | Boolean | true | false | 是否显示loading |
|
||||
| loadingText | String | 二维码生成中 | | loading文字 |
|
||||
|
||||
### 方法
|
||||
|
||||
| 方法名 | 参数 | 默认值 | 说明 |
|
||||
| :----------- | :--: | :----: | :-------------------------------------------------- |
|
||||
| _makeCode() | | | 生成二维码 |
|
||||
| _clearCode() | | | 清空二维码(清空二维码会触发result回调 返回值为空) |
|
||||
| _saveCode() | | | 保存二维码到图库 |
|
||||
|
||||
### 事件
|
||||
|
||||
| 事件名 | 返回值 | 说明 |
|
||||
| :----- | :----------------------------: | --------------------------------------: |
|
||||
| result | 生成的图片base64或图片临时地址 | 返回二维码路径 注:_clearCode()后返回空 |
|
||||
|
||||
### 感谢
|
||||
|
||||
[uni-app](https://uniapp.dcloud.io/ "uni-app")
|
||||
[qrcode](https://github.com/aralejs/qrcode "qrcode")
|
||||
205
src/components/geek-xd/components/geek-qrcode/geek-qrcode.vue
Normal file
205
src/components/geek-xd/components/geek-qrcode/geek-qrcode.vue
Normal file
@@ -0,0 +1,205 @@
|
||||
<template xlang="wxml" minapp="mpvue">
|
||||
<view class="geek-qrcode">
|
||||
<canvas class="geek-qrcode-canvas" :canvas-id="cid" :style="{width:cpSize+'px',height:cpSize+'px'}" />
|
||||
<image v-show="show" :src="result" :style="{width:cpSize+'px',height:cpSize+'px'}" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QRCode from "./qrcode.js"
|
||||
let qrcode
|
||||
export default {
|
||||
name: "geek-qrcode",
|
||||
props: {
|
||||
cid: {
|
||||
type: String,
|
||||
default: 'geek-qrcode-canvas'
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
unit: {
|
||||
type: String,
|
||||
default: 'upx'
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
val: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
foreground: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
pdground: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
iconSize: {
|
||||
type: Number,
|
||||
default: 40
|
||||
},
|
||||
lv: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
onval: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loadMake: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
usingComponents: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showLoading: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
default: '二维码生成中'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
_makeCode() {
|
||||
let that = this
|
||||
if (!this._empty(this.val)) {
|
||||
qrcode = new QRCode({
|
||||
context: that, // 上下文环境
|
||||
canvasId:that.cid, // canvas-id
|
||||
usingComponents: that.usingComponents, // 是否是自定义组件
|
||||
showLoading: that.showLoading, // 是否显示loading
|
||||
loadingText: that.loadingText, // loading文字
|
||||
text: that.val, // 生成内容
|
||||
size: that.cpSize, // 二维码大小
|
||||
background: that.background, // 背景色
|
||||
foreground: that.foreground, // 前景色
|
||||
pdground: that.pdground, // 定位角点颜色
|
||||
correctLevel: that.lv, // 容错级别
|
||||
image: that.icon, // 二维码图标
|
||||
imageSize: that.iconSize,// 二维码图标大小
|
||||
cbResult: function (res) { // 生成二维码的回调
|
||||
that._result(res)
|
||||
},
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '二维码内容不能为空',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
},
|
||||
_clearCode() {
|
||||
this._result('')
|
||||
qrcode.clear()
|
||||
},
|
||||
_saveCode() {
|
||||
let that = this;
|
||||
if (this.result != "") {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: that.result,
|
||||
success: function () {
|
||||
uni.showToast({
|
||||
title: '二维码保存成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
_result(res) {
|
||||
this.result = res;
|
||||
this.$emit('result', res)
|
||||
},
|
||||
_empty(v) {
|
||||
let tp = typeof v,
|
||||
rt = false;
|
||||
if (tp == "number" && String(v) == "") {
|
||||
rt = true
|
||||
} else if (tp == "undefined") {
|
||||
rt = true
|
||||
} else if (tp == "object") {
|
||||
if (JSON.stringify(v) == "{}" || JSON.stringify(v) == "[]" || v == null) rt = true
|
||||
} else if (tp == "string") {
|
||||
if (v == "" || v == "undefined" || v == "null" || v == "{}" || v == "[]") rt = true
|
||||
} else if (tp == "function") {
|
||||
rt = false
|
||||
}
|
||||
return rt
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
size: function (n, o) {
|
||||
if (n != o && !this._empty(n)) {
|
||||
this.cSize = n
|
||||
if (!this._empty(this.val)) {
|
||||
setTimeout(() => {
|
||||
this._makeCode()
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
},
|
||||
val: function (n, o) {
|
||||
if (this.onval) {
|
||||
if (n != o && !this._empty(n)) {
|
||||
setTimeout(() => {
|
||||
this._makeCode()
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cpSize() {
|
||||
if(this.unit == "upx"){
|
||||
return uni.upx2px(this.size)
|
||||
}else{
|
||||
return this.size
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
if (this.loadMake) {
|
||||
if (!this._empty(this.val)) {
|
||||
setTimeout(() => {
|
||||
this._makeCode()
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.geek-qrcode {
|
||||
position: relative;
|
||||
}
|
||||
.geek-qrcode-canvas {
|
||||
position: fixed;
|
||||
top: -99999upx;
|
||||
left: -99999upx;
|
||||
z-index: -99999;
|
||||
}
|
||||
</style>
|
||||
1206
src/components/geek-xd/components/geek-qrcode/qrcode.js
Normal file
1206
src/components/geek-xd/components/geek-qrcode/qrcode.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<view :style="labelStyle" class="title">{{ label }}</view>
|
||||
<view :style="numberStyle" class="number">{{ formatNumber(number,props.place) }}</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
default: "订单数量"
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 300
|
||||
},
|
||||
labelColor: {
|
||||
type: String,
|
||||
default: '#white'
|
||||
},
|
||||
labelSize: {
|
||||
type: Number,
|
||||
default: 16
|
||||
},
|
||||
number: {
|
||||
type: Number,
|
||||
default: 80
|
||||
},
|
||||
numberColor: {
|
||||
type: String,
|
||||
default: 'red'
|
||||
},
|
||||
numberSize: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
place: {
|
||||
type: Number,
|
||||
default: 2
|
||||
}
|
||||
})
|
||||
const labelStyle = computed(() => {
|
||||
return {
|
||||
width: `${props.width}rpx`,
|
||||
color: props.labelColor,
|
||||
fontSize: `${props.labelSize}px`
|
||||
}
|
||||
})
|
||||
|
||||
const numberStyle = computed(() => {
|
||||
return {
|
||||
width: `${props.width}rpx`,
|
||||
color: props.numberColor,
|
||||
fontSize: `${props.numberSize}px`
|
||||
}
|
||||
})
|
||||
|
||||
function formatNumber(num,place) {
|
||||
|
||||
let fixedNum = Number(num).toFixed(place); // 将数字保留两位小数
|
||||
let parts = fixedNum.split('.'); // 拆分整数部分和小数部分
|
||||
let integerPart = parts[0]; // 整数部分
|
||||
let decimalPart = parts[1]; // 小数部分
|
||||
|
||||
// 使用padStart方法补0到小数部分
|
||||
decimalPart = decimalPart.padStart(place, '0');
|
||||
|
||||
return integerPart + '.' + decimalPart;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.number {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
17
src/components/geek-xd/types/index.ts
Normal file
17
src/components/geek-xd/types/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface Menu {
|
||||
icon: string,
|
||||
label: string
|
||||
}
|
||||
|
||||
export interface Commodity {
|
||||
img: string,
|
||||
title: string,
|
||||
subTitle: string,
|
||||
price: number
|
||||
}
|
||||
|
||||
export interface CommodityOrder extends Commodity {
|
||||
shop: string,
|
||||
status: string,
|
||||
num: number
|
||||
}
|
||||
Reference in New Issue
Block a user