Ver Fonte

【Add】导入抽奖插件

liuxiangxin há 6 meses atrás
pai
commit
d80804c211

+ 7 - 0
pages.json

@@ -146,6 +146,13 @@
 			{
 				"navigationBarTitleText" : "可用商品"
 			}
+		},
+		{
+			"path" : "pages/score/lottery",
+			"style" : 
+			{
+				"navigationBarTitleText" : "积分抽奖"
+			}
 		}
 	],
 	"globalStyle": {

+ 16 - 0
uni_modules/lime-dialer/changelog.md

@@ -0,0 +1,16 @@
+## 0.2.5(2024-11-11)
+- fix: 优化styleOpt样式
+## 0.2.4(2024-07-19)
+- chore: 更新文档,增加背景框
+## 0.2.3(2024-05-27)
+- fix: 修复只有2项时无法显示的问题
+## 0.2.2(2024-05-07)
+- chore: stylus 改成 scss
+- fix: 修复vue3点击多触发问题
+## 0.2.1(2023-05-08)
+- chore: 增加示例
+## 0.2.0(2021-07-09)
+- chore: 统一命名规范,无须主动引入组件
+## 0.1.0(2021-06-16)
+- 首次上传
+- 纯CSS实现的抽奖转盘

+ 130 - 0
uni_modules/lime-dialer/components/l-dialer/index.scss

@@ -0,0 +1,130 @@
+
+@mixin theme($property, $variable) {
+	$theme: (
+		'dialer_text_color': #ffb400,
+		'dialer_prize_font_size': 12px,
+		'dialer_prize_name_padding': 8px,
+		'dialer_prize_inner_padding': 8px,
+		'dialer_prize_image_size': 36px
+	);
+
+	$value: map-get($theme, $variable);
+	#{$property}: $value;
+	
+	/* #ifndef APP-IOS || APP-ANDROID */
+	$css-variable: var(--#{$variable}, #{$value});
+	#{$property}: #{$css-variable};
+	/* #endif */
+}
+
+.l-dialer {
+  position: relative;
+
+  &__inner {
+    width: 100%;
+    height: 100%;
+	flex:1;
+    position: relative;
+    @include theme('color', 'dialer_text_color');
+    background-repeat: no-repeat;
+    background-size: cover;
+    box-sizing: border-box;
+	border-radius: 999px;
+	overflow: hidden;
+	// transition: transform 3s ease;
+	// transform-origin: 50% 50%;
+	transition-property: transform;
+	transition-timing-function: cubic-bezier(0.250, 0.460, 0.455, 0.995);
+    &-border {
+      position: absolute;
+      left: 0;
+      top: 0;
+      bottom: 0;
+      right: 0;
+    }
+
+    &-wrap {
+		position: relative;
+		z-index: 1;
+		width: 100%;
+		height: 100%;
+		border-radius: 999px;
+		overflow: hidden;
+		box-sizing: border-box;
+		// background: red;
+		/* #ifndef APP-ANDROID */
+		&::after {
+			position: absolute;
+			left: 0;
+			top: 0;
+			bottom: 0;
+			right: 0;
+			content: '';
+			border-radius: 50%;
+			box-shadow: 0 0 20rpx currentColor inset;
+		}
+		/* #endif */
+    }
+
+    &-item {
+      overflow: hidden;
+      position: absolute;
+      top: -50%;
+      left: 50%;
+      width: 100%;
+      height: 100%;
+      transform-origin: 0 100%;
+    }
+
+    &-content {
+      position: absolute;
+      @include theme('padding-top', 'dialer_prize_inner_padding');
+      box-sizing: border-box;
+      width: 100%;
+      height: 100%;
+      left: -50%;
+      bottom: -50%;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    &-name {
+      @include theme('padding-top', 'dialer_prize_name_padding');
+      @include theme('padding-bottom', 'dialer_prize_name_padding');
+      @include theme('font-size', 'dialer_prize_font_size');
+      @include theme('color', 'dialer_text_color');
+    }
+
+    &-img {
+      @include theme('width', 'dialer_prize_image_size');
+      @include theme('height', 'dialer_prize_image_size');
+    }
+  }
+
+  &__pointer {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    z-index: 1;
+  }
+}
+
+/* #ifndef APP-IOS || APP-ANDROID */
+.heart {
+  animation: heart 1s infinite;
+}
+
+@keyframes heart {
+  0% {
+    transform: scale(1);
+  }
+  25% {
+    transform: scale(1.03);
+  }
+  to {
+    transform: scale(1);
+  }
+}
+/* #endif */

+ 111 - 0
uni_modules/lime-dialer/components/l-dialer/index.styl

@@ -0,0 +1,111 @@
+replace2(val)
+	r = match('\$[^() ]+', val, 'gi')
+	re = val
+	for v, i in r
+		k = split(v, re)
+		j = s('%s', convert(v))
+		re = join(j, k)
+	unquote(re)
+
+theme($property, $imp)
+	a = replace('(\$[^() ]+)', '$1', $imp)
+	// #ifndef APP-NVUE
+	b = replace('(\$)([^() ]+)', 'var(--$2, $1$2)', $imp)
+	// #endif
+	{$property} replace2(a)
+	// #ifndef APP-NVUE
+	{$property} replace2(b)
+	// #endif
+		
+$dialer_text_color ?= #ffb400
+$dialer_prize_font_size ?= 12px
+$dialer_prize_name_padding ?= 8px
+$dialer_prize_inner_padding ?= 8px
+$dialer_prize_image_size ?= 36px
+
+.l-dialer
+	position relative
+	&__inner
+		width 100%
+		height 100%
+		position relative
+		// color $dialer_text_color
+		theme('color', '$dialer_text_color')
+		background-repeat no-repeat
+		background-size cover
+		box-sizing border-box
+		&-border
+			position absolute
+			left 0
+			top 0
+			bottom 0
+			right 0
+		&-wrap
+			position relative
+			z-index 1
+			// flex 1
+			width 100%
+			height 100%
+			border-radius 50%
+			overflow hidden
+			box-sizing border-box
+			
+			&::after
+				position absolute
+				left 0
+				top 0
+				bottom 0
+				right 0
+				content ''
+				border-radius 50%
+				box-shadow 0 0 20rpx currentColor inset 
+		&-item
+			overflow hidden
+			position absolute
+			top -50%
+			left 50%
+			width 100%
+			height 100%
+			transform-origin 0 100%
+		&-content
+			position absolute
+			theme('padding-top', '$dialer_prize_inner_padding')
+			// padding-top $dialer_prize_inner_padding
+			box-sizing border-box
+			width 100%
+			height 100%
+			left -50%
+			bottom -50%
+			display flex
+			flex-direction column
+			align-items center
+		&-name
+			theme('padding-top', '$dialer_prize_name_padding')
+			theme('padding-bottom', '$dialer_prize_name_padding')
+			theme('font-size', '$dialer_prize_font_size')
+			theme('color', '$dialer_text_color')
+			// padding-top $dialer_prize_name_padding
+			// padding-bottom $dialer_prize_name_padding
+			// font-size $dialer_prize_font_size
+			// color $dialer_text_color
+		&-img
+			// margin-top 24rpx
+			theme('width', '$dialer_prize_image_size')
+			theme('height', '$dialer_prize_image_size')
+			// width $dialer_prize_image_size
+			// height $dialer_prize_image_size
+	&__pointer
+		position absolute
+		left 50%
+		top 50%
+		transform translate(-50%, -50%)
+		z-index 1
+.heart
+	animation heart 1s infinite
+@keyframes heart
+	0%
+		transform scale(1)
+	25%
+		transform scale(1.03)
+	to
+		transform scale(1)

+ 260 - 0
uni_modules/lime-dialer/components/l-dialer/l-dialer.uvue

@@ -0,0 +1,260 @@
+<template>
+	<view class="l-dialer" :style="rootStyles">
+		<view class="l-dialer__inner" :style="innerStyle">
+			<view class="l-dialer__inner-border" v-if="$slots['border'] != null">
+				<slot name="border" />
+			</view>
+			<view class="l-dialer__inner-wrap" ref="drawbleRef" :style="wrapStyle">
+				<view class="l-dialer__inner-item" v-for="(item, index) in prizeList" :key="index"
+					:style="itemStyle(index)">
+					<view class="l-dialer__inner-content" :style="contentStyle(index)">
+						<slot v-if="$slots['prize'] != null" name="prize" :item="item" :even="index % 2"></slot>
+						<template v-else>
+							<text class="l-dialer__inner-name" :style="nameStyle">{{ item['name'] }}</text>
+							<image class="l-dialer__inner-img" :src="item['img']"></image>
+						</template>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="l-dialer__pointer" :style="pointerStyle">
+			<slot v-if="$slots['pointer'] != null" name="pointer" />
+			<image v-else :class="!isTurnIng ? 'heart' : ''" src="/uni_modules/lime-dialer/static/turnable_btn.png"
+				style="width: 100%" mode="widthFix" @tap="$emit('click')" />
+		</view>
+	</view>
+</template>
+<script lang="uts" setup>
+	const emits = defineEmits(['click', 'done'])
+	const slots = defineSlots<{
+		prize : {
+			item : UTSJSONObject,
+			even : number
+		}
+	}>()
+	const props = defineProps({
+		size: {
+			// #ifdef APP-ANDROID
+			type: Object,
+			//  #endif
+			// #ifndef APP-ANDROID
+			type: [String, Number],
+			//  #endif
+			default: 300
+		},
+		prizeList: {
+			type: Array as PropType<UTSJSONObject[]>,
+			default: () : UTSJSONObject[] => []
+		},
+		turns: {
+			type: Number,
+			default: 10
+		},
+		duration: {
+			type: Number,
+			default: 3
+		},
+		styleOpt: {
+			type: Object as PropType<UTSJSONObject>,
+			default: () : UTSJSONObject => ({
+				// 每一块扇形的背景色,默认值,可通过父组件来改变
+				prizeBgColors: ['#fff0a3', '#fffce6'],
+				// 每一块扇形的外边框颜色,默认值,可通过父组件来改变
+				borderColor: '#ffd752',
+			} as UTSJSONObject)
+		},
+		customStyle: {
+			type: String,
+		},
+		dialStyle: {
+			type: String,
+		},
+		pointerStyle: {
+			type: String,
+			default: `width: 30%`
+		}
+	})
+
+	const drawbleRef = ref<UniElement | null>(null)
+	const startRotateDegree = ref(0)
+	const rotateAngle = ref('rotate(0deg)')
+	const rotateTransition = ref('')
+	const isTurnIng = ref(false)
+
+
+	const getStyleOpt = computed(() : UTSJSONObject => {
+		const style = {
+			// 每一块扇形的背景色,默认值,可通过父组件来改变
+			prizeBgColors: ['#fff0a3', '#fffce6'],
+			// 每一块扇形的外边框颜色,默认值,可通过父组件来改变
+			borderColor: '#ffd752',
+		}
+		return UTSJSONObject.assign(style, props.styleOpt)
+	})
+	const rootStyles = computed(() : string => {
+		const size = /\d$/.test(`${props.size}`) ? `${props.size}px` : props.size;
+		return `width: ${size}; height: ${size}; ${props.customStyle}`
+	})
+
+	const innerStyle = computed(() : string => {
+		// const style = new Map<string, string>()
+		let style = ''
+		const padding = getStyleOpt.value['padding'] ?? 0
+
+		style += `padding: ${padding};`
+		style += `transform: ${rotateAngle.value};`
+		style += `${rotateTransition.value};`//`transition: ${rotateTransition.value};`
+		style += `${props.dialStyle};`
+
+		return style
+	})
+
+	const wrapStyle = computed(() : string => {
+		const borderColor = getStyleOpt.value['borderColor']
+		if (borderColor != null) {
+			return `border: 1rpx solid ${borderColor}`
+		}
+		return ''
+	})
+
+	const itemStyle = computed(() : ((index : number) => Map<string, any>) => {
+		return (index : number) : Map<string, any> => {
+			const length = props.prizeList.length;
+			const prizeBgColors : string[] = (getStyleOpt.value['prizeBgColors'] ?? [] as string[]) as string[]
+			const prizeBgColorsLength = prizeBgColors.length;
+			const borderColor = getStyleOpt.value['borderColor']
+			const style = new Map<string, any>();
+			// #ifndef APP
+			if (length == 2) {
+				// style['transform'] = index == 0 ? 0 : `rotate(270deg)` 
+				style.set('transform', index == 0 ? `rotate(0deg)` : `rotate(270deg)`)
+				style.set('top', 0)
+			} else {
+				style.set('transform', `rotate(${(360 / length) * index}deg) skewX(0deg) skewY(${360 / length - 90}deg)`);
+			}
+			if (prizeBgColorsLength > 0) {
+				style.set('backgroundColor', `${prizeBgColors[index % prizeBgColorsLength]}`)
+			}
+			if (borderColor != null) {
+				style.set('border', `1rpx solid ${borderColor}`)
+			}
+			// #endif
+			// #ifdef APP
+			if (length == 2) {
+				style.set('backgroundColor', `${prizeBgColors[index % prizeBgColorsLength]}`)
+				style.set('transform', index == 0 ? `rotate(0deg)` : `rotate(270deg)`);
+				style.set('top', 0)
+				if (borderColor != null) {
+					style.set('border', `1rpx solid ${borderColor}`)
+				}
+			} else {
+				style.set('transform', `rotate(${(360 / length) * index}deg)`);
+			}
+
+			// #endif
+			return style
+		}
+	})
+
+	const contentStyle = computed(() : ((index : number) => string) => {
+		return (index : number) : string => {
+			// #ifndef APP
+			if (props.prizeList.length != 2) {
+				return `transform: skewY(${90 - 360 / props.prizeList.length}deg) skewX(0deg) rotate(${180 / props.prizeList.length}deg)`
+			} else {
+				return index == 0
+					? `transform: rotate(90deg); bottom: 0`
+					: `transform: rotate(0deg); bottom: -50%; left: 0`
+			}
+
+			// #endif
+			// #ifdef APP
+			if (props.prizeList.length != 2) {
+				return `transform: rotate(${180 / props.prizeList.length}deg)`
+			} else {
+				return index == 0
+					? `transform: rotate(90deg); bottom: 0`
+					: `transform: rotate(0deg); bottom: -50%; left: 0`
+			}
+
+			// #endif
+		}
+
+	})
+
+	const nameStyle = computed(() : Map<string, any> => {
+		const fontSize = getStyleOpt.value['fontSize']
+		const color = getStyleOpt.value['color']
+		const style = new Map<string, any>()
+
+		if (fontSize != null) {
+			style.set('fontSize', fontSize)
+		}
+		if (color != null) {
+			style.set('color', color)
+		}
+		return style
+	})
+
+
+	const run = (index : number) => {
+		if (isTurnIng.value) return
+		const duration = props.duration;
+		const length = props.prizeList.length;
+
+		const _rotateAngle = startRotateDegree.value + props.turns * 360 + 360 - (180 / length + (360 / length) * index) - (startRotateDegree.value % 360);
+		startRotateDegree.value = _rotateAngle;
+		rotateAngle.value = `rotate(${_rotateAngle}deg)`;
+		rotateTransition.value = `transition-duration: ${duration}s`;
+		isTurnIng.value = true
+		setTimeout(() => {
+			emits('done', index);
+			isTurnIng.value = false
+		}, duration * 1000 + 500);
+	}
+	// #ifdef APP
+	onMounted(() => {
+		nextTick(() => {
+			if (drawbleRef.value == null) return;
+			const ctx = drawbleRef.value!.getDrawableContext()!;
+			const size = drawbleRef.value!.offsetWidth;
+			watch(props.prizeList, () => {
+				ctx.reset()
+				const length = props.prizeList.length;
+				if (length == 2) return
+				const prizeBgColors : string[] = (getStyleOpt.value['prizeBgColors'] ?? [] as string[]) as string[]
+				const prizeBgColorsLength = prizeBgColors.length;
+				const borderColor = getStyleOpt.value['borderColor'] as string | null
+
+				const centerX = size / 2;
+				const centerY = size / 2;
+				const radius = size / 2;
+
+				const angle = (2 * Math.PI) / length;
+
+				for (let i = 0; i < length; i++) {
+					ctx.beginPath();
+					ctx.moveTo(centerX, centerY);
+					ctx.arc(centerX, centerY, radius, i * angle, (i + 1) * angle);
+					ctx.lineTo(centerX, centerY);
+					ctx.closePath();
+					ctx.fillStyle = prizeBgColors[i % prizeBgColorsLength];
+					if (borderColor != null) {
+						ctx.lineWidth = 2
+						ctx.strokeStyle = borderColor;
+						ctx.stroke()
+					}
+					ctx.fill();
+				}
+				ctx.update()
+			}, { immediate: true })
+		})
+	})
+	// #endif
+	defineExpose({
+		run
+	})
+</script>
+<style lang="scss" scoped>
+	@import './index';
+</style>

+ 176 - 0
uni_modules/lime-dialer/components/l-dialer/l-dialer.vue

@@ -0,0 +1,176 @@
+<template>
+	<view class="l-dialer" :style="getStyle">
+		<view class="l-dialer__inner" :style="getDialStyle">
+			<view class="l-dialer__inner-border" v-if="$slots.border">
+				<slot name="border"/>
+			</view>
+			<view class="l-dialer__inner-wrap" :style="styleOpt.borderColor && (' border: 1rpx solid ' + styleOpt.borderColor)">
+				<view class="l-dialer__inner-item" v-for="(item, index) in prizeList" :key="index" :style="[getRotateAngle(index)]">
+					<view class="l-dialer__inner-content" :style="[getCorrectAngle(index)]">
+						<slot v-if="$slots.prize" name="prize" :item="item" :even="index % 2"></slot>
+						<block v-else>
+							<view class="l-dialer__inner-name" :style="[{fontSize: styleOpt.fontSize, color: styleOpt.color}]">{{ item.name }}</view>
+							<image class="l-dialer__inner-img" :src="item.img"></image>
+						</block>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="l-dialer__pointer" :style="pointerStyle" >
+			<slot v-if="$slots && $slots.pointer" name="pointer"/>
+			<image
+				v-else
+				:class="!isTurnIng ? 'heart': ''"
+				src="/uni_modules/lime-dialer/static/turnable_btn.png" 
+				style="width: 100%"
+				mode="widthFix" 
+				@tap="$emit('click')"
+			/>
+		</view>
+	</view>
+</template>
+<script>
+// import {addUnit} from '@/uni_modules/lime-shared/addUnit'	
+// import {sleep} from '@/uni_modules/lime-shared/sleep'	
+export default {
+	name: 'l-dialer',
+	emits: ['click', 'done'],
+	props: {
+		size: {
+			type: [String, Number],
+			default: 300
+		},
+		prizeList: {
+			type: Array
+		},
+		turns: {
+			type: Number,
+			default: 10
+		},
+		duration: {
+			type: Number,
+		    default: 3
+		},
+		styleOpt: {
+			type: Object,
+			default: () => ({
+				// 每一块扇形的背景色,默认值,可通过父组件来改变
+				// $primary-1 $primary-2 
+				prizeBgColors: ['#fff0a3', '#fffce6'],
+				// 每一块扇形的外边框颜色,默认值,可通过父组件来改变
+				// primary-4
+				borderColor: '#ffd752',
+			})
+		},
+		customStyle: {
+			type: String,
+		},
+		dialStyle: {
+			type: String,
+		},
+		pointerStyle: {
+			type: String,
+			default: `width: 30%`
+		}
+	},
+	data() {
+		return {
+			// 开始转动的角度
+			startRotateDegree: 0,
+			// 设置指针默认指向的位置,现在是默认指向2个扇形之间的边线上
+			rotateAngle: 0,
+			rotateTransition: '',
+			isTurnIng: false,
+		};
+	},
+	computed: {
+		getStyleOpt() {
+			const style = {
+				// 每一块扇形的背景色,默认值,可通过父组件来改变
+				prizeBgColors: ['#fff0a3', '#fffce6'],
+				// 每一块扇形的外边框颜色,默认值,可通过父组件来改变
+				borderColor: '#ffd752',
+			}
+			return Object.assign(style, this.styleOpt)
+		},
+		getRotateAngle() {
+			return index => {
+				const style = {
+					transform: `rotate(${(360 / this.prizeList.length) * index}deg) skewX(0deg) skewY(${360 / this.prizeList.length - 90}deg)`,
+					backgroundColor: `${this.getStyleOpt.prizeBgColors[index % this.getStyleOpt.prizeBgColors.length]}`,
+					border: `${this.getStyleOpt.borderColor && '1rpx solid ' + this.getStyleOpt.borderColor }`
+				}
+				if(this.prizeList.length == 2) {
+					style['transform'] = index == 0 ? 0 : `rotate(270deg)` //`rotate(${(360 / this.prizeList.length) * index}deg)`
+					style['top']  = 0
+				} 
+				return style
+				// return {
+				// 	transform: `rotate(${(360 / this.prizeList.length) * index}deg) skewX(0deg) skewY(${360 / this.prizeList.length - 90}deg)`,
+				// 	backgroundColor: `${this.styleOpt.prizeBgColors[index % this.styleOpt.prizeBgColors.length]}`,
+				// 	border: `${this.styleOpt.borderColor && '1rpx solid ' + this.styleOpt.borderColor }`
+				// }
+			};
+		},
+		getCorrectAngle() {
+			return index => {
+				const style = {
+					transform: `skewY(${90 - 360 / this.prizeList.length}deg) skewX(0deg) rotate(${180 / this.prizeList.length}deg)`
+				}
+				if(this.prizeList.length == 2){
+					if(index == 0) {
+						style['transform'] = `rotate(90deg)` 
+						style['bottom'] = 0
+					} else {
+						style['transform'] = `rotate(0deg)` 
+						style['left'] = 0
+						style['bottom'] = '-50%'
+					}
+					
+				}
+				return style
+			};
+		},
+		getStyle() {
+			let { size, customStyle } = this;
+			//addUnit(size)//
+			size = /\d$/.test(size) ? size + 'px' : size;
+			return `width: ${size}; height: ${size}; ${customStyle}`;
+		},
+		getDialStyle() {
+			return `
+				padding: ${this.getStyleOpt.padding};
+				transform: ${this.rotateAngle};
+				transition: ${this.rotateTransition};
+				${this.dialStyle}
+			`;
+		}
+		
+	},
+	methods: {
+		// 转动起来
+		run(index) {
+			if(this.isTurnIng) return
+			const duration = this.duration;
+			const length = this.prizeList.length
+			
+			const rotateAngle = this.startRotateDegree + this.turns * 360 + 360 - (180 / length + (360 / length) * index) - (this.startRotateDegree % 360);
+			this.startRotateDegree = rotateAngle;
+			this.rotateAngle = `rotate(${rotateAngle}deg)`;
+			this.rotateTransition = `transform ${duration}s cubic-bezier(0.250, 0.460, 0.455, 0.995)`;
+			this.isTurnIng = true
+			// sleep(duration * 1000 + 500).then(() => {
+			// 	this.$emit('done', index);
+			// 	this.isTurnIng = false
+			// })
+			setTimeout(() => {
+				this.$emit('done', index);
+				this.isTurnIng = false
+			}, duration * 1000 + 500);
+		}
+	}
+};
+</script>
+<style lang="scss" scoped>
+@import './index';
+</style>

Diff do ficheiro suprimidas por serem muito extensas
+ 2 - 0
uni_modules/lime-dialer/components/lime-dialer/lime-dialer.uvue


Diff do ficheiro suprimidas por serem muito extensas
+ 2 - 0
uni_modules/lime-dialer/components/lime-dialer/lime-dialer.vue


+ 82 - 0
uni_modules/lime-dialer/package.json

@@ -0,0 +1,82 @@
+{
+	"id": "lime-dialer",
+	"displayName": "幸运转盘",
+	"version": "0.2.5",
+	"description": "幸运转盘 抽奖 抽奖转盘,兼容uniapp/uniappX(h5,ios,安卓)",
+	"keywords": [
+        "转盘",
+        "抽奖",
+        "抽奖转盘"
+    ],
+	"repository": "",
+	"engines": {
+		"HBuilderX": "^3.4.12"
+	},
+	"dcloudext": {
+		"sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+		"npmurl": "",
+		"type": "component-vue"
+	},
+	"uni_modules": {
+		"dependencies": [],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+                "aliyun": "y",
+                "alipay": "n"
+			},
+			"client": {
+				"Vue": {
+					"vue2": "y",
+					"vue3": "y"
+				},
+				"App": {
+                    "app-vue": "y",
+                    "app-nvue": "n",
+                    "app-uvue": "y",
+                    "app-harmony": "u"
+                },
+				"H5-mobile": {
+					"Safari": "y",
+					"Android Browser": "y",
+					"微信浏览器(Android)": "y",
+					"QQ浏览器(Android)": "y"
+				},
+				"H5-pc": {
+					"Chrome": "y",
+					"IE": "y",
+					"Edge": "y",
+					"Firefox": "y",
+					"Safari": "y"
+				},
+				"小程序": {
+					"微信": "y",
+					"阿里": "y",
+					"百度": "y",
+					"字节跳动": "y",
+					"QQ": "y"
+				},
+				"快应用": {
+					"华为": "y",
+					"联盟": "y"
+				}
+			}
+		}
+	}
+}

+ 176 - 0
uni_modules/lime-dialer/readme.md

@@ -0,0 +1,176 @@
+# Dialer 转盘抽奖 
+> 营销活动类组件  
+> [查看更多](https://limeui.qcoon.cn/#/dialer) <br>
+
+
+
+### 平台兼容
+|	H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ小程序 | App |
+|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
+| √	| √ |	√	| √ |	√	| √ |	√ |
+
+
+### 代码演示
+#### 基础用法
+
+```html
+<l-dialer :prizeList="prizeList" @click="onClick" @done="onDone" ref="dialer" />
+```
+```js
+export default {
+    data() {
+        return {
+			// 奖品列表,
+            prizeList: [
+            	{
+            		id: 'coupon88',
+            		name: '8.8折',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/175718/35/12595/5477/60b660c6Eb850717b/a1cfe750dcdb5b78.png',
+            	},
+            	{
+            		id: 'coupon900',
+            		Color: 'rgb(251, 219, 216)',
+            		name: '900',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/190845/9/6092/4489/60b65fe8Ebb8f8284/955da889f6d1c13e.png',
+            	},
+            	{
+            		id: 'coupon1',
+            		name: '1元',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/189927/14/6092/4174/60b66173E23c472ea/44af15a151defca1.png',
+            	},
+            	{
+            		id: 'apple',
+            		Color: 'rgba(246, 142, 46, 0.5)',
+            		name: '苹果手机',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/177670/26/4591/2514/60a25874Ee0e5332a/99c7bdfede732ae4.png'
+            	},
+            	{
+            		id: 'coupon210',
+            		name: '210元',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/124578/12/20170/4429/60b635d8E7089ebb0/7a47d76a2a260cc0.png'
+            	},
+            	{
+            		id: 'jd100',
+            		name: '100京豆',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/162790/37/15087/28046/6062a49aE8f2c10f2/5591ff0ff38a45e2.png',
+            	},
+            	{
+            		id: 'coupon400',
+            		name: '400元',
+            		img: 'https://img11.360buyimg.com/pop/jfs/t1/177090/2/7001/4535/60b6607aEe9c1db2a/76c67675f547db3f.png'
+            	},
+            	{
+            		id: 'thanks',
+            		name: '谢谢参与',
+            		img: 'https://storage.jd.com/cdn-upload/dialTemplateHeart.png',
+            	}
+            ]
+        };
+    },
+    methods: {
+		onDone(index) {
+			const prize = this.prizeList[index]
+			uni.showModal({
+				title: prize.id == 'thanks' ? '很遗憾': '恭喜您',
+				content: (prize.id !== 'thanks' ? `获得`:'') + prize.name
+			})
+		},
+		onClick() {
+			// 奖品的索引
+			this.$refs.dialer.run(5)
+		}
+	}
+}
+```
+
+#### 表框
+- 1、通过设置`dial-style`设置背景的方式设置,必须是网络图片
+- 2、通过插槽`border`设置
+
+```html
+// 方式1
+<l-dialer dial-style="color: rgba(60,48,158,0.7); padding: 32rpx;background-image: url(http://a.cn/static/dialer/lottery-bg.png)"/>
+
+// 方式2
+<l-dialer>
+	<image slot="border" src="static/dialer/lottery-bg.png"/>
+</l-dialer>
+```
+
+#### 指针
+- 1、可通过`pointer-style`设置背景的方式设置,但必须为网络图片
+- 2、可通过插槽`pointer`设置
+- 3、因为插件是能过获取内部方法实现抽奖,只要获取方法,任何元素都是指针按钮
+
+```html
+// 方式1
+<l-dialer pointer-style="background-image: url(http://a.cn/static/dialer/bg.png)"/>
+// 方式2
+<l-dialer>
+	<image slot="pointer" src="static/dialer/lottery-bg.png" />
+</l-dialer>
+```
+
+#### 奖品插槽
+- 默认会按奖品列表渲染,但想更个性可通过插槽`prize`设置
+- 微信小程序最好使用HX3.7.12+并且在`manifest.json`设置`slotMultipleInstance`
+```json
+"mp-weixin" : {
+    "slotMultipleInstance" : true
+}
+```
+
+```html
+<l-dialer>
+	<template #prize="{item}">
+		<image style="width: 72rpx; height: 72rpx;" :src="item.img" />
+	</template>
+</l-dialer>
+```
+
+
+### 查看示例
+- 导入后直接使用这个标签查看演示效果
+
+```html
+<!-- // 代码位于 uni_modules/lime-dialer/compoents/lime-dialer -->
+<lime-dialer />
+```
+
+
+### 插件标签
+- 默认 l-dialer 为 component
+- 默认 lime-dialer 为 demo
+
+
+
+### API
+#### Props
+
+| 参数 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| size | 转盘直径,默认单位为 `rpx` | Number | `300` | - |
+| prizeList | 奖品列表  | Array | [] | - |
+| turns | 旋转圈数 | Number | `10` | - |
+| duration | 旋转过程时间,单位为 `s` | Number | `3` | - |
+| styleOpt | 转盘中的样式,包括每个扇区的背景颜色(在每条数据中页可单独设置prizeColor),扇区的边框颜色 | Object | {prizeBgColors: [],borderColor: ''} | - |
+| customStyle | 外容器的自定义样式 | String |  | - |
+| dialStyle | 转盘自定义样式 | String |  | - |
+| pointerStyle | 指针自定义样式 | String | `width:30%` | - |
+
+#### Event
+
+| 名称 | 说明                                                       |
+| ---- | ---------------------------------------------------------- |
+| run(index)   | 旋转到指定索引,该事件是通过`ref`获取插件实例的内部方法 |
+| done   | 旋转结束,该事件是通过标签接收的方法 |
+| click   | 点击指针,该事件是通过标签接收的方法 |
+
+
+#### Slots
+
+| 名称 | 说明                                                       |
+| ---- | ---------------------------------------------------------- |
+| border   | 边框插槽 |
+| prize   | 奖品插槽 |
+| pointer   | 指针插槽 |

BIN
uni_modules/lime-dialer/static/lottery-bg-.png


BIN
uni_modules/lime-dialer/static/turnable_btn.png


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff