forked from angelo/web-retail-h5
				
			
		
			
	
	
		
			385 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
		
		
			
		
	
	
			385 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
|  | <template> | ||
|  | 	<view class="table pr" :style="'zoom:'+size+';'"> | ||
|  | 		<view class="v-tr" style="display: flex;"> | ||
|  | 			<view class="v-td" :class="{ | ||
|  | 					colspan: Array.isArray(treeData.children) ? treeData.children.length * 2 : 1, | ||
|  | 					parentLevel: Array.isArray(treeData.children) && treeData.children.length, | ||
|  | 					extend: Array.isArray(treeData.children) && treeData.children.length && treeData.extend | ||
|  | 				}"> | ||
|  | 				<view :class="{ node: true }"> | ||
|  | 					<view class="person" :class="Array.isArray(treeData.class) ? treeData.class : []"> | ||
|  | 						<view @click.stop="clickNode(treeData)"> | ||
|  | 							<image class="person-ava1" :src="treeData.avatarUrl" mode=""></image> | ||
|  | 
 | ||
|  | 							<view class="person_flex"> | ||
|  | 								<view class="flex-p1"> | ||
|  | 									<image class="person-ava" :src="treeData.countryUrl2" mode=""> | ||
|  | 									</image> | ||
|  | 									<view class=""> | ||
|  | 										{{treeData.memberCode}} | ||
|  | 									</view> | ||
|  | 								</view> | ||
|  | 								<view class="flex-p1"> | ||
|  | 									<image class="person-ava" :src="treeData.settleCountryUrl2" mode=""> | ||
|  | 									</image> | ||
|  | 									<view class=""> | ||
|  | 										{{treeData.name}} | ||
|  | 									</view> | ||
|  | 								</view> | ||
|  | 							</view> | ||
|  | 						</view> | ||
|  | 						<view @click.stop="clickTop(treeData)" class="goTop_btn" | ||
|  | 							:style="{ backgroundColor:`${treeData.color}`}"> | ||
|  | 							置顶 | ||
|  | 						</view> | ||
|  | 					</view> | ||
|  | 				</view> | ||
|  | 			</view> | ||
|  | 		</view> | ||
|  | 		<view class="v-tr" v-if="Array.isArray(treeData.children) && treeData.children.length && treeData.extend"> | ||
|  | 			<view v-for="(children, index) in treeData.children" :key="index" colspan="2" class="childLevel v-td"> | ||
|  | 				<TreeChart :json="children" :left="0" :top="0" @click-node="clickNode" @click-top='clickTop' /> | ||
|  | 			</view> | ||
|  | 		</view> | ||
|  | 	</view> | ||
|  | </template> | ||
|  | 
 | ||
|  | <script> | ||
|  | 	export default { | ||
|  | 		name: 'TreeChart', | ||
|  | 		props: ['json', 'size'], | ||
|  | 		data() { | ||
|  | 			return { | ||
|  | 				treeData: {} | ||
|  | 			}; | ||
|  | 		}, | ||
|  | 		watch: { | ||
|  | 			json: { | ||
|  | 				handler: function(Props) { | ||
|  | 					let extendKey = function(jsonData) { | ||
|  | 						jsonData.extend = jsonData.extend === void 0 ? true : !!jsonData.extend; | ||
|  | 						if (Array.isArray(jsonData.children)) { | ||
|  | 							jsonData.children.forEach(c => { | ||
|  | 								extendKey(c); | ||
|  | 							}); | ||
|  | 						} | ||
|  | 						return jsonData; | ||
|  | 					}; | ||
|  | 					if (Props) { | ||
|  | 						this.treeData = extendKey(Props); | ||
|  | 					} | ||
|  | 				}, | ||
|  | 				immediate: true | ||
|  | 			} | ||
|  | 		}, | ||
|  | 		methods: { | ||
|  | 			toggleExtend: function(treeData) { | ||
|  | 				treeData.extend = !treeData.extend; | ||
|  | 				this.$forceUpdate(); | ||
|  | 			}, | ||
|  | 			clickNode(e) { | ||
|  | 				this.$emit('click-node', e) | ||
|  | 			}, | ||
|  | 			clickTop(e) { | ||
|  | 				this.$emit('click-top', e) | ||
|  | 			} | ||
|  | 		} | ||
|  | 	}; | ||
|  | </script> | ||
|  | 
 | ||
|  | <style scoped> | ||
|  | 	.f18 { | ||
|  | 		font-size: 18rpx; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.pv-btn { | ||
|  | 		width: 200rpx; | ||
|  | 		height: 50rpx; | ||
|  | 		background-color: #b2821e; | ||
|  | 		color: #fff; | ||
|  | 		font-size: 20rpx; | ||
|  | 		line-height: 50rpx; | ||
|  | 		display: flex; | ||
|  | 		align-items: center; | ||
|  | 		margin: auto; | ||
|  | 		margin-top: 12rpx; | ||
|  | 		margin-bottom: 12rpx; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.next-btn { | ||
|  | 		border-radius: 50%; | ||
|  | 		background: none; | ||
|  | 		width: 40rpx; | ||
|  | 		height: 40rpx; | ||
|  | 		margin: auto; | ||
|  | 		padding: 0; | ||
|  | 		display: flex; | ||
|  | 		justify-content: center; | ||
|  | 		align-items: center; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.table { | ||
|  | 		border-collapse: separate !important; | ||
|  | 		border-spacing: 0 !important; | ||
|  | 		width: 100%; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.v-tr { | ||
|  | 
 | ||
|  | 		display: inline-flex; | ||
|  | 		justify-content: center; | ||
|  | 		align-items: flex-start; | ||
|  | 		/* width: 100%; */ | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.v-td { | ||
|  | 		position: relative; | ||
|  | 		vertical-align: top; | ||
|  | 		padding: 0 0 130rpx 0; | ||
|  | 		text-align: center; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.extend_handle { | ||
|  | 		position: absolute; | ||
|  | 		left: 50%; | ||
|  | 		bottom: 30rpx; | ||
|  | 		width: 10rpx; | ||
|  | 		height: 10rpx; | ||
|  | 		padding: 10rpx; | ||
|  | 		transform: translate3d(-30rpx, 0, 0); | ||
|  | 		cursor: pointer; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.extend_handle:before { | ||
|  | 		content: ''; | ||
|  | 		display: block; | ||
|  | 		width: 100%; | ||
|  | 		height: 100%; | ||
|  | 		box-sizing: border-box; | ||
|  | 		border: 4rpx solid; | ||
|  | 		border-color: #f2f2f2 #f2f2f2 transparent transparent; | ||
|  | 		transform: rotateZ(135deg); | ||
|  | 		transform-origin: 50% 50% 0; | ||
|  | 		transition: transform ease 300ms; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.extend_handle:hover:before { | ||
|  | 		border-color: #f2f2f2 #f2f2f2 transparent transparent; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.extend .extend_handle:before { | ||
|  | 		transform: rotateZ(-45deg); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.extend::after { | ||
|  | 		content: ''; | ||
|  | 		position: absolute; | ||
|  | 		left: 50%; | ||
|  | 		bottom: 84rpx; | ||
|  | 		height: 84rpx; | ||
|  | 		border-left: 4rpx solid #f2f2f2; | ||
|  | 		transform: translate3d(-2rpx, 0, 0); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.childLevel::before { | ||
|  | 		content: ''; | ||
|  | 		position: absolute; | ||
|  | 		left: 50%; | ||
|  | 		bottom: 100%; | ||
|  | 		height: 84rpx; | ||
|  | 		border-left: 4rpx solid #f2f2f2; | ||
|  | 		transform: translate3d(-2rpx, 0, 0); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.childLevel::after { | ||
|  | 		content: ''; | ||
|  | 		position: absolute; | ||
|  | 		left: 0; | ||
|  | 		right: 0; | ||
|  | 		top: -88rpx; | ||
|  | 		border-top: 4rpx solid #f2f2f2; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.childLevel:first-child:before, | ||
|  | 	.childLevel:last-child:before { | ||
|  | 		display: none; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.childLevel:first-child:after { | ||
|  | 		left: 50%; | ||
|  | 		height: 84rpx; | ||
|  | 		border: 4rpx solid; | ||
|  | 		border-color: #f2f2f2 transparent transparent #f2f2f2; | ||
|  | 		border-radius: 6rpx 0 0 0; | ||
|  | 		transform: translate3d(2rpx, 0, 0); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.childLevel:last-child:after { | ||
|  | 		right: 50%; | ||
|  | 		height: 84rpx; | ||
|  | 		border: 4rpx solid; | ||
|  | 		border-color: #f2f2f2 #f2f2f2 transparent transparent; | ||
|  | 		border-radius: 0 6rpx 0 0; | ||
|  | 		transform: translate3d(-2rpx, 0, 0); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.childLevel:first-child.childLevel:last-child::after { | ||
|  | 		left: auto; | ||
|  | 		border-radius: 0; | ||
|  | 		border-color: transparent #f2f2f2 transparent transparent; | ||
|  | 		transform: translate3d(2rpx, 0, 0); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node { | ||
|  | 		position: relative; | ||
|  | 		display: inline-block; | ||
|  | 		margin: 0 10rpx; | ||
|  | 		box-sizing: border-box; | ||
|  | 		text-align: center; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person { | ||
|  | 		position: relative; | ||
|  | 		display: inline-block; | ||
|  | 		z-index: 2; | ||
|  | 		/* width: 138rpx; */ | ||
|  | 		/* height:53rpx; */ | ||
|  | 		padding: 23rpx 50rpx; | ||
|  | 		background-color: #ffffff; | ||
|  | 		box-shadow: 0rpx 3rpx 7rpx 0rpx rgba(0, 0, 0, 0.15); | ||
|  | 		border-radius: 15rpx; | ||
|  | 		font-size: 22rpx; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.person_flex { | ||
|  | 		display: flex; | ||
|  | 		padding: 10rpx 20rpx; | ||
|  | 		box-shadow: 0rpx 3rpx 7rpx 0rpx rgba(0, 0, 0, 0.15); | ||
|  | 		margin: 0rpx 0 20rpx 0; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.flex-p1 { | ||
|  | 		margin: 0 5rpx; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .person-ava { | ||
|  | 		width: 88rpx; | ||
|  | 		height: 53rpx; | ||
|  | 		border-radius: 10rpx; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .person-ava1 { | ||
|  | 		width: 104rpx; | ||
|  | 		height: 104rpx; | ||
|  | 		border-radius: 50%; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.goTop_btn { | ||
|  | 		padding: 5rpx 10rpx; | ||
|  | 		border-radius: 8rpx; | ||
|  | 		font-size: 22rpx; | ||
|  | 		width: 88rpx; | ||
|  | 		margin: 0 auto; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .avat { | ||
|  | 		display: block; | ||
|  | 		width: 4em; | ||
|  | 		height: 4em; | ||
|  | 		margin: auto; | ||
|  | 		overflow: hidden; | ||
|  | 		background: #fff; | ||
|  | 		border: 4px solid #f2f2f2; | ||
|  | 		box-sizing: border-box; | ||
|  | 		border-radius: 0.5em; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .avat img { | ||
|  | 		width: 100%; | ||
|  | 		height: 100%; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .name { | ||
|  | 		display: block; | ||
|  | 		margin: auto; | ||
|  | 		overflow: hidden; | ||
|  | 		box-sizing: border-box; | ||
|  | 		overflow: hidden; | ||
|  | 		font-size: 20rpx; | ||
|  | 		line-height: 1.5; | ||
|  | 		padding-top: 24rpx; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .name-bottom { | ||
|  | 		display: block; | ||
|  | 		margin: auto; | ||
|  | 		overflow: hidden; | ||
|  | 		border-top: none; | ||
|  | 		box-sizing: border-box; | ||
|  | 		overflow: hidden; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.node .person .operation {} | ||
|  | 
 | ||
|  | 	.node.hasMate::after { | ||
|  | 		content: ''; | ||
|  | 		position: absolute; | ||
|  | 		left: 2em; | ||
|  | 		right: 2em; | ||
|  | 		top: 2em; | ||
|  | 		border-top: 4px solid #f2f2f2; | ||
|  | 		z-index: 1; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/* 横板 */ | ||
|  | 	.landscape { | ||
|  | 		transform: translate(-100%, 0) rotate(-90deg); | ||
|  | 		transform-origin: 100% 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .node { | ||
|  | 		text-align: left; | ||
|  | 		height: 8em; | ||
|  | 		width: 8em; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .person { | ||
|  | 		position: relative; | ||
|  | 		transform: rotate(90deg); | ||
|  | 		padding-left: 4.5em; | ||
|  | 		height: 4em; | ||
|  | 		top: 4em; | ||
|  | 		left: -1em; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .person .avat { | ||
|  | 		position: absolute; | ||
|  | 		left: 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .person .name { | ||
|  | 		height: 4em; | ||
|  | 		line-height: 4em; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .hasMate { | ||
|  | 		position: relative; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .hasMate .person { | ||
|  | 		position: absolute; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .hasMate .person:first-child { | ||
|  | 		left: auto; | ||
|  | 		right: -4em; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	.landscape .hasMate .person:last-child { | ||
|  | 		left: -4em; | ||
|  | 		margin-left: 0; | ||
|  | 	} | ||
|  | </style> |