init with my components for uniapp
This commit is contained in:
		
						commit
						419ba35c1f
					
				
							
								
								
									
										99
									
								
								cColorText/cColorText.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								cColorText/cColorText.vue
									
									
									
									
									
										Normal 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)){
 | 
			
		||||
        // TIC地址被精心设计为24字节,32个b64字符,不需要填充
 | 
			
		||||
        // 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
									
								
							
							
						
						
									
										252
									
								
								cPager/cPager.vue
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										211
									
								
								cQrcode/cQrcode.vue
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										1201
									
								
								cQrcode/qrcode.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										276
									
								
								cToast/cToast.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								cToast/cToast.vue
									
									
									
									
									
										Normal 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 loading(string),默认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>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user