init with my components for uniapp

This commit is contained in:
陆柯 2020-03-23 19:44:24 +08:00
commit 419ba35c1f
5 changed files with 2039 additions and 0 deletions

99
cColorText/cColorText.vue Normal file
View File

@ -0,0 +1,99 @@
<script>
export default {
name: 'cColorText',
props: {
colorText: {
type: String,
default: ''
},
type: {
type: String,
default: 'hex'
}
},
data() { return {
}},
methods: {
num2hex(value){ // num
if (value) {
switch (typeof value){
case 'number': value = value.toString(16); break;
case 'string': // hex = parseInt(value).toString(16); break;
default:
}
}
return value
},
shrinkHex(hex){
if (/^(0x)?[\dA-F]+$/i.test(hex)){
return hex.replace(/^0x/, '').replace(/^(\w{18})\w*(\w{18})$/, '$1$2')
}
return ''
},
hex2color(hex){
if (/^(0x)?[0-9A-Fa-f]+$/.test(hex)){
hex.replace(/^0x/, '')
let len=hex.length
let rest = len % 6
let fullLength = len + (6-(rest?rest:6)) // ?:
hex = hex.padEnd(fullLength, '0')
return hex.match(/[0-9A-Fa-f]{6}/g)
}
return []
},
address2colorB64u(address){ // TIC address should be in b64u format, i.e. base64 for url (+ to -, / to _)
if (/^[0-9a-zA-Z\-_]+$/.test(address)){
// TIC2432b64
// let len=address.length
// let rest = len % 4
// let fullLength = len + (4-(rest?rest:4))
// address = address.padEnd(fullLength, 'A') // b64 '00'A.
let colorArray = address.match(/[0-9A-Za-z\-_]{4}/g)
return colorArray
}
return []
},
b64u2hex(b64u){
if (/^[0-9a-zA-Z\-_]+$/.test(b64u)){
let b64 = b64u.replace(/\-/g, '+').replace(/_/g, '/')
return Buffer.from(b64, 'base64').toString('hex')
}
return null
}
}
}
</script>
<template>
<view class="sColorText">
<template v-if="type==='hex'">
<span class="sColorCode"
v-for="(color,index) in hex2color(shrinkHex(colorText))"
:style="{background:`#${color}`}"
:key="index">
{{color}}
</span>
</template>
<template v-else-if="type==='b64u'">
<span class="sColorCode"
v-for="(colorB64u,index) in address2colorB64u(colorText)"
:style="{background:`#${b64u2hex(colorB64u)}`}"
:key="index">
{{colorB64u}}
</span>
</template>
</view>
</template>
<style lang="scss" scoped>
.sColorText{
display: flex;
flex-flow: row nowrap;
font-family: 'Courier New';
color: white;
span{
padding: 2px 0;
}
}
</style>

252
cPager/cPager.vue Normal file
View File

@ -0,0 +1,252 @@
<script>
// based on Pagination https://ext.dcloud.net.cn/plugin?id=32
export default {
name: 'cPager',
props: {
prevText: {
type: String,
default: 'Prev'
},
nextText: {
type: String,
default: 'Next'
},
current: {
type: [Number, String],
default: 1
},
total: { //
type: [Number, String],
default: 0
},
pageSize: { //
type: [Number, String],
default: 10
},
showIcon: { // icon
type: [Boolean, String],
default: true
},
showEdge: {
type: [Boolean, String],
default: false
}
},
data() {
return {
currentIndex: 1
}
},
computed: {
maxPage() {
let maxPage = 1
let total = Number(this.total)
let pageSize = Number(this.pageSize)
if (total && pageSize) {
maxPage = Math.ceil(total / pageSize)
}
return maxPage
}
},
watch: {
current(val) {
this.currentIndex = +val
}
},
created() {
this.currentIndex = +this.current
},
methods: {
clickLeftMost(){
this.currentIndex = 1
this.change('leftMost')
},
clickLeft() {
if (Number(this.currentIndex) === 1) {
return
}
this.currentIndex -= 1
this.change('prev')
},
clickRight() {
if (Number(this.currentIndex) === this.maxPage) {
return
}
this.currentIndex += 1
this.change('next')
},
clickRightMost() {
if (Number(this.currentIndex) === this.maxPage) {
return
}
this.currentIndex = this.maxPage
this.change('rightMost')
},
change(e) {
this.$emit('change', {
type: e,
current: this.currentIndex
})
}
}
}
</script>
<template>
<view class="uni-pagination">
<view class="uni-pagination__btns">
<view v-if="(showEdge===true || showEdge==='true')" class="uni-pagination__btn" @click="clickLeftMost"> <!-- always enabled so as to refresh -->
<template v-if="showIcon===true || showIcon === 'true'">
<view class="sLeftMostButton"></view>
</template>
<template v-else><text class="uni-pagination__child-btn">{{ leftMostText }}</text></template>
</view>
<view class="uni-pagination__btn" :class="currentIndex === 1 ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
:hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'" :hover-start-time="20" :hover-stay-time="70"
@click="clickLeft">
<template v-if="showIcon===true || showIcon === 'true'">
<view class="sPrevButton"></view>
</template>
<template v-else><text class="uni-pagination__child-btn">{{ prevText }}</text></template>
</view>
<view class="uni-pagination__btn" :class="currentIndex === maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
:hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20" :hover-stay-time="70"
@click="clickRight">
<template v-if="showIcon===true || showIcon === 'true'">
<view class="sNextButton"></view>
</template>
<template v-else><text class="uni-pagination__child-btn">{{ nextText }}</text></template>
</view>
<view v-if="(showEdge===true || showEdge==='true')" class="uni-pagination__btn" :class="currentIndex === maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
:hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20" :hover-stay-time="70"
@click="clickRightMost">
<template v-if="showIcon===true || showIcon === 'true'">
<view class="sRightMostButton"></view>
</template>
<template v-else><text class="uni-pagination__child-btn">{{ rightMostText }}</text></template>
</view>
</view>
<view class="uni-pagination__num">
<view class="uni-pagination__num-current">
<text class="uni-pagination__num-current-text" style="color:#007aff">{{ currentIndex }}</text><text class="uni-pagination__num-current-text">/{{ maxPage || 0 }}</text>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.uni-pagination {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
/* #ifdef APP-NVUE */
padding: 0 20px;
/* #endif */
width: 400px;
position: relative;
overflow: hidden;
flex-direction: row;
justify-content: center;
align-items: center;
}
.uni-pagination__btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
justify-content: space-between;
align-items: center;
flex-direction: row;
}
.uni-pagination__btn {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 60px;
height: 30px;
line-height: 30px;
font-size: $uni-font-size-base;
position: relative;
// background-color: $uni-bg-color-grey;
flex-direction: row;
justify-content: center;
align-items: center;
text-align: center;
}
.uni-pagination__child-btn {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
font-size: $uni-font-size-base;
position: relative;
flex-direction: row;
justify-content: center;
align-items: center;
text-align: center;
}
.uni-pagination__num {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
position: absolute;
margin: 0 auto;
top: 0;
flex-direction: row;
justify-content: center;
align-items: center;
width: 50px;
height: 30px;
line-height: 30px;
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-pagination__num-current {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-pagination__num-current-text {
font-size: 15px;
}
.uni-pagination--enabled {
color: #333333;
opacity: 1;
}
.uni-pagination--disabled {
opacity: 0.3;
}
.uni-pagination--hover {
color: rgba(0, 0, 0, .6);
background-color: $uni-bg-color-hover;
}
.sLeftMostButton, .sPrevButton, .sNextButton, .sRightMostButton{
width: 20px;
height: 20px;
background: no-repeat center center / contain;
}
.sLeftMostButton{
background-image: url(../../static/Common.leftMost.png)
}
.sPrevButton{
background-image: url(../../static/Common.previous.png)
}
.sNextButton{
background-image: url(../../static/Common.next.png)
}
.sRightMostButton{
background-image: url(../../static/Common.rightMost.png)
}
</style>

211
cQrcode/cQrcode.vue Normal file
View File

@ -0,0 +1,211 @@
<template xlang="wxml" minapp="mpvue">
<view class="cQrcode">
<!-- #ifndef MP-ALIPAY -->
<canvas class="cQrcode-canvas" :canvas-id="cid" :style="{width:cpSize+'px',height:cpSize+'px'}" />
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<canvas :id="cid" :width="cpSize" :height="cpSize" class="cQrcode-canvas" />
<!-- #endif -->
<image v-show="show" :src="result" :style="{width:cpSize+'px',height:cpSize+'px'}" />
</view>
</template>
<script>
// Based on tki-qrcode https://github.com/q310550690/uni-app-qrcode , https://ext.dcloud.net.cn/plugin?id=39
import QRCode from "./qrcode.js"
let qrcode
export default {
name: "cQrcode",
props: {
cid: {
type: String,
default: 'cQrcodeCanvas'
},
size: {
type: [Number, String],
default: 200
},
unit: {
type: String,
default: 'px'
},
show: {
type: [Boolean, String],
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, String],
default: 40
},
lv: {
type: [Number, String],
default: 3
},
onval: {
type: [Boolean, String],
default: true
},
loadMake: {
type: [Boolean, String],
default: true
},
usingComponents: {
type: [Boolean, String],
default: true
},
showLoading: {
type: [Boolean, String],
default: false
},
loadingText: {
type: String,
default: '......'
},
},
data() {
return {
result: '../static/Common.loading.qrcode.png',
}
},
methods: {
_makeCode() {
let that = this
if (!this._empty(this.val)) {
qrcode = new QRCode({
context: that, //
canvasId:that.cid, // canvas-id
usingComponents: that.usingComponents===true||that.usingComponents==='true', //
showLoading: that.showLoading===true||that.showLoading==='true', // loading
loadingText: that.loadingText, // loading
text: that.val, //
size: that.cpSize, //
background: that.background, //
foreground: that.foreground, //
pdground: that.pdground, //
correctLevel: Number(that.lv), //
image: that.icon, //
imageSize: Number(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===true || this.onval==='true') {
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===true || this.loadMake==='true') {
if (!this._empty(this.val)) {
setTimeout(() => {
this._makeCode()
}, 0);
}
}
},
}
</script>
<style>
.cQrcode {
position: relative;
}
.cQrcode-canvas {
position: fixed;
top: -99999upx;
left: -99999upx;
z-index: -99999;
}
</style>

1201
cQrcode/qrcode.js Normal file

File diff suppressed because it is too large Load Diff

276
cToast/cToast.vue Normal file
View File

@ -0,0 +1,276 @@
<!--
based on
https://ext.dcloud.net.cn/plugin?id=672
https://github.com/steffenx/uniapp_popup
*数组形式传值
*type,类型 success warn info fail loadingstring默认info
*content,内容string
*duration,消失时间Number默认2000
*distance,弹窗间距默认128可设为0代表重叠
*isClick,是否点击消失Boolean默认false
-->
<template>
<view class="popup_list">
<view v-for="(items,index) of popup_list" :id="items.uuid" :key="items.uuid" >
<view class="mpopup" :style="{ background: items.color ,top:index*items.distance+50+'px'}" :class="[items.animator,items.typeClass]" @click="close(items.uuid,index)">
<view class="pic"><image class="icon" mode="aspectFit" :src="items.icon"></image></view>
<text class="text" :style="{ color: items.colortext }">{{ items.content }}</text>
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
popup_list:[],//
}
},
props:{
},
methods:{
init:function(toast){
if (toast.type == 'success') {
toast.icon = toast.icon || '../static/Common.success.png';
toast.typeClass='mpopup-success';
return toast;
}
if (toast.type == 'warn') {
toast.icon = toast.icon || '../static/Common.warn.png';
toast.typeClass='mpopup-warn';
return toast;
}
if (toast.type == 'info') {
toast.icon = toast.icon || '../static/Common.info.png';
toast.typeClass='mpopup-info';
return toast;
}
if (toast.type == 'fail') {
toast.icon = toast.icon || '../static/Common.fail.png';
toast.typeClass='mpopup-fail';
return toast;
}
if (toast.type == 'loading') {
toast.icon = toast.icon || '../../static/xuan-popup/loading.png';
toast.typeClass='mpopup-loading';
return toast;
}
},
open:function(toast){
//uuid
let uuid=this.guid();
toast.uuid=uuid;
//
toast.animator='fade_Down';
toast.isClick = toast.isClick || false ///
toast.duration = toast.duration || 1500
toast.distance = toast.distance || 128 //
toast.type = toast.type || 'info'
//
let newToast=this.init(toast);
//
this.popup_list.push(newToast);
if(!newToast.isClick){
this.disappear(newToast.uuid,newToast.duration);
}//
else{
this.$emit('uuidCallback',newToast.uuid);
}
},
//
disappear:function(uuid,duration){
//退
this.fade_out_animator(uuid,duration).then(res=>{
setTimeout(()=>{
for(let i=0;i<this.popup_list.length;i++){
if(this.popup_list[i].uuid==res){
//
this.popup_list.splice(i,1);
this.$forceUpdate()
}
}
},250)
});
},
fade_out_animator:function(uuid,duration){
//duration退
if(!duration||typeof(duration)!='number'){duration=1500;}
return new Promise(res=>{
setTimeout(()=>{
for(let i=0;i<this.popup_list.length;i++){
if(this.popup_list[i].uuid==uuid){
//退
this.popup_list[i].animator='fade_Top';
res(uuid);
}
}
},duration)
})
},
//
close:function(uuid,ind){
if(ind){
if(!this.popup_list[ind].isClick){return}
}
this.remove_element(uuid).then((res)=>{
setTimeout(()=>{
for(let i=0;i<this.popup_list.length;i++){
if(this.popup_list[i].uuid==res){
//
this.popup_list.splice(i,1);
this.$emit('closeCallback',uuid);
this.$forceUpdate()
}
}
},250)
})
},
//
remove_element:function(uuid){
return new Promise(res=>{
for (var i = 0; i < this.popup_list.length; i++) {
if(this.popup_list[i].uuid==uuid){
this.popup_list[i].animator='fade_Top';
res(uuid)
break;
}
}
})
},
//
update:function(update_list){
for (var i = 0; i < this.popup_list.length; i++) {
if(this.popup_list[i].uuid==update_list.uuid){
this.popup_list[i].type=update_list.type;
this.init(this.popup_list[i]);
this.popup_list[i].content=update_list.content;
break;
}
}
},
//uuid
guid:function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
}
}
</script>
<style lang="scss">
.mpopup{
display: flex;
flex-direction: column;
text-align: center;
justify-content: center;
align-items: center;
min-height: 45px;
max-width: 80%;
transition :all .5s;
position: fixed;
right:0;
left:0;
margin: 0 auto;
border-radius: 5px;
z-index:998;
@media screen and (min-width: 751px) { max-width: 500px }
.pic{
display: flex;
text-align: center;
justify-content: center;
width: 32px;
height: 32px;
margin: 20px;
.icon{
width: 100%;
height: auto;
}
}
.text{
margin: 0px 20px 20px 20px;
font-size: 16px;
}
}
.mpopup-success{
background: #f0f9eb;
border: 1px solid #e1f3d8;
color: #67c23a;
}
.mpopup-fail{
background: #fef0f0;
border: 1px solid #fde2e2;
color: #f56c6c;
}
.mpopup-warn{
background: #fdf6ec;
border: 1px solid #faecd8;
color: #e6a23c;
}
.mpopup-info{
background: #edf2fc;
border: 1px solid #ebeef5;
color: #909399;
}
.mpopup-loading{
background: #e2f5ff;
border: 1px solid #ceeeff;
color: #5cbaff;
image{
animation: rotate360 1.5s ease infinite;
}
}
.fade_Down{
animation: fadeInDown 0.6s both;
}
.fade_Top{
animation: fadeInTop 0.5s forwards;
}
/*从上到下*/
@keyframes fadeInDown
{
from {
opacity: 0;
-webkit-transform: translate(0,-100px);
transform: stranslate(0,-100px);
}
to {
opacity:1;
-webkit-transform: translate(0,10px);
transform: stranslate(0,10px);
}
}
/*从下到上*/
@keyframes fadeInTop
{
from {
opacity:1;
-webkit-transform: translate(0,10px);
transform: stranslate(0,10px);
}
to {
opacity: 0;
-webkit-transform: translate(0,-100px);
transform: stranslate(0,-100px);
}
}
@keyframes rotate360
{
from {
transform: rotate(0);
}
to{
transform: rotate(360deg);
}
}
</style>