Преглед на файлове

Merge branch 'master' of http://47.98.226.240:3000/twt/operatingCompany

* 'master' of http://47.98.226.240:3000/twt/operatingCompany:
  111
  picker
  时间选择器
  1
guo преди 3 години
родител
ревизия
4b2ba1eaf1
променени са 29 файла, в които са добавени 3755 реда и са изтрити 24 реда
  1. 667 0
      operatingCompany/components/chose-city/chose-city.vue
  2. 47 0
      operatingCompany/components/nodata/nodata.vue
  3. 429 0
      operatingCompany/components/timeChose/timeChose.vue
  4. 85 5
      operatingCompany/pages/entryReport/entered.vue
  5. 12 3
      operatingCompany/pages/entryReport/entryReport.vue
  6. 56 16
      operatingCompany/pages/reportManage/reportManage.vue
  7. BIN
      operatingCompany/static/img/baiheiback.png
  8. BIN
      operatingCompany/static/img/icon_luru@2x.png
  9. BIN
      operatingCompany/static/img/icon_luruhou@2x.png
  10. BIN
      operatingCompany/static/img/jiantou.png
  11. 37 0
      operatingCompany/uni_modules/uni-popup/changelog.md
  12. 45 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
  13. 263 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
  14. 143 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
  15. 185 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
  16. 7 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/en.json
  17. 8 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/index.js
  18. 7 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
  19. 7 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
  20. 45 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/keypress.js
  21. 26 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/popup.js
  22. 403 0
      operatingCompany/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
  23. 89 0
      operatingCompany/uni_modules/uni-popup/package.json
  24. 296 0
      operatingCompany/uni_modules/uni-popup/readme.md
  25. 13 0
      operatingCompany/uni_modules/uni-transition/changelog.md
  26. 128 0
      operatingCompany/uni_modules/uni-transition/components/uni-transition/createAnimation.js
  27. 277 0
      operatingCompany/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
  28. 83 0
      operatingCompany/uni_modules/uni-transition/package.json
  29. 397 0
      operatingCompany/uni_modules/uni-transition/readme.md

+ 667 - 0
operatingCompany/components/chose-city/chose-city.vue

@@ -0,0 +1,667 @@
+<template>
+	<view class="chose-city">
+		<view>
+			<view class="status_bar" :style="{height: iStatusBarHeight + 'px'}" v-if="topshow"></view>
+			<view class="nav" v-if="topshow">城市选择
+			  <image src="../../static/img/goback.png" mode="" class="foback" @click="closeModal"></image>
+			</view>
+		</view>
+		<!-- 城市搜索 -->
+		<view class="city-search-wrap">
+			<view class="search">
+				<view class="l-search">
+					<view class="icon-search">
+						<view class="cuIcon-search"></view>
+					</view>
+					<input class="input-search" type="text" :value="inputValue" placeholder="请输入城市" placeholder-style="color:#8E8F97"
+					 :focus="searchFocus" @input="searchChange" />
+					<text class="clear-input iconfont icon-icon-test" v-if="isClearBtn" @click="inputValue = ''"></text>
+				</view>
+				<view class="r-cancel" @click="closeModal">取消</view>
+			</view>
+			<!-- 搜索列表  -->
+			<view class="reach-content" v-show="inputValue">
+				<block v-show="searchData.length">
+					<view class="li" v-for="item in searchData" :key="item.citycode" @click="selectCity(item)">
+						{{item.name}}
+					</view>
+				</block>
+				<view class="has-no-data" v-show="hasNoData">没有找到匹配数据~</view>
+			</view>
+		</view>
+		<!-- 城市列表 -->
+		<scroll-view class="scroll-view" scroll-y scroll-with-animation="true" enable-back-to-top="true" :scroll-into-view="toIndex"
+		 @scroll="scrollHandle" v-if="!inputValue">
+			<view class="block">
+				<!-- 您所在的地区 -->
+				<view class="area list-item" id="area">
+					<view class="title-wrapp">
+						<view class="c-title">
+							<text class="l">定位城市</text>
+						</view>
+					</view>
+					<view class="ul">
+						<!-- <view class="li now font-clamp" @click="selectCity(myCityObj,'refresh')">
+							<image src="https://fulu-mall.oss-cn-hangzhou.aliyuncs.com/e0e5e497b1714e8fa6135df32e4bf114.png" class="icon"
+							 v-if="hasLocation"></image>
+							<image src="https://fulu-mall.oss-cn-hangzhou.aliyuncs.com/8ed89f5bcaac48c6bd9139261f86c6b6.png" class="icon"
+							 v-else></image>
+							<text class="text">{{ hasLocation ? myCityObj.name:'定位失败' }}</text>
+						</view> -->
+						<view @click="selectCity(citydw)">{{citydw.name}}</view>
+					</view>
+				</view>
+				<!-- 历史记录 -->
+				<!-- <view class="area list-item" id="record" v-if="recordList.length">
+					<view class="title-wrapp">
+						<view class="c-title">
+							<text class="l">历史记录</text>
+						</view>
+					</view>
+					<view class="ul">
+						<view class="li font-clamp" v-for="item in recordList" :key="item.citycode" @click="selectCity(item)">
+							{{ item.name }}
+						</view>
+					</view>
+				</view> -->
+			</view>
+			<!-- 城市列表  -->
+			<view class="city-list">
+				<view class="list list-item" v-for="(item, key) of cityList" :key="key" :id="item.nameType">
+					<view class="c-title">{{ item.nameType }}</view>
+					<view class="item" v-for="innerItem in item.list" :key="innerItem.citycode" @click="selectCity(innerItem)">
+						{{ innerItem.name }}
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+
+		<!-- 字母列表 -->
+		<view class="alphabet" @touchstart="touchStart" @touchend="touchEnd" @touchmove.stop="touchMove">
+			<view v-for="(item, index) in alphabet" :key="index" @touchstart="getLetter" @touchend="setLetter" :id="item">
+				<view class="item" :class="{ active: currentLetter == item }">
+					{{ item == 'area' ? '当前' : item == 'record' ? '历史' : item }}
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import cityJson from '@/static/dataJson/city.json'
+	export default {
+		props:{
+			 topshow:{            //参数名
+			   type:Boolean,      //定义传值的类型
+			   default:false    //参数默认
+			} 
+		},
+		data() {
+			return {
+				isIPX: null,
+				regionId: null, // 区域ID
+				isToggle: true,
+				isReach: false,
+				inputValue: '',
+				searchData: [], // 搜索的数据
+				isClearBtn: false,
+				toIndex: '', // 跳转的索引的字母
+				tipsLetter: '', // 滑动显示字母
+				timer: null,
+				hasNoData: false,
+				searchFocus: false,
+				letterDetails: [],
+				currentLetter: 'area', //默认选择
+				cityArr: [],
+				recordList: [],
+				cityList: [],
+				hasLocation: false,
+				myCityObj: {},
+				alphabet:[],
+				iStatusBarHeight:'',
+				lng:'',
+				lat:'',
+				cityname:'',
+				cityCode:'',
+				citydw:{
+					name:'',
+					citycode:'',
+				}
+			};
+		},
+		mounted() {
+			 this.iStatusBarHeight = uni.getSystemInfoSync().statusBarHeight;
+			this.cityArr = cityJson.data.list
+			if (this.cityArr && this.cityArr[0]) {
+				this.cityArr.map(v => {
+					v.nameType = v.pinyin.substr(0, 1)
+				})
+				this.cityList = this.groupArr(this.cityArr, 'nameType')
+			}
+			this.recordList = cityJson.data.recordList
+			this.alphabet = cityJson.data.alphabet
+			this.getLocation()
+		},
+		watch: {
+			// 城市搜索输入框
+			inputValue(newVal) {
+				this.isClearBtn = newVal ? true : false;
+
+				if (this.timer) {
+					clearTimeout(this.timer);
+				}
+
+				if (!this.inputValue) {
+					this.searchData = [];
+					return;
+				}
+				this.timer = setTimeout(() => {
+					const result = [];
+					this.cityList.map(v => {
+						v.list.forEach((item) => {
+							if (/^[a-zA-Z]+$/.test(item.pinyin) && item.pinyin.toLowerCase().includes(this.inputValue.toLowerCase()) ||
+								item.name.includes(this.inputValue)) {
+								result.push(item);
+							}
+						});
+					})
+					this.searchData = result;
+					if (this.searchData.length === 0) {
+						this.hasNoData = true;
+					} else {
+						this.hasNoData = false;
+					}
+				}, 500);
+			},
+			isReach(val) {
+				this.searchFocus = val;
+			},
+		},
+		methods: {
+			getLocation() {
+				const that = this
+				/* uni.getLocation({
+					// #ifdef MP-ALIPAY
+					type: 'gcj02',
+					// #endif
+					success(res) {
+						console.log('---',res)
+						res.name = res.city
+						res.citycode = res.cityAdcode
+						that.myCityObj = res
+						that.hasLocation = true
+						uni.setStorageSync('nowCityObj', res)
+					},
+					fail(err) {
+						that.hasLocation = false
+						uni.showToast({
+							icon:'none',
+							title: '获取用户定位失败,请手动选择当前城市'
+						})
+					},
+				}) */
+				uni.getLocation({
+				    type: 'gcj02',
+				    success: function (res) {
+				       console.log(res)
+						that.lng=res.longitude
+						that.lat=res.latitude
+						that.getAdress();
+						
+				    },
+					 fail(err) {
+						console.log(err)
+						
+					 }
+				}); 
+			},
+			getAdress(){
+				var location=this.lng+','+this.lat
+				uni.request({
+				    url: 'https://restapi.amap.com/v3/place/around', //仅为示例,并非真实接口地址。
+				    data: {
+				        key: '064b6a4a8ade55656edcde2f528876de',
+						location: location,
+						types:"190000",
+						extensions:"all",
+						radius:100
+				    },
+				    dataType: "json",
+				    success: (res) => {
+				        console.log(res);
+				        this.cityname=res.data.pois[0].cityname;
+						var cityCode=res.data.pois[0].adcode
+						cityCode=cityCode.slice(0, -2)
+						cityCode=cityCode+'00'
+						this.cityCode=cityCode
+						this.citydw.name=this.cityname
+						this.citydw.citycode=this.cityCode
+				    }
+				});
+			},
+			groupArr(list, field) {
+				var fieldList = [],
+					att = [];
+				list.map((e) => {
+					fieldList.push(e[field])
+				})
+				//数组去重
+				fieldList = fieldList.filter((e, i, self) => {
+					return self.indexOf(e) == i
+				})
+				for (var j = 0; j < fieldList.length; j++) {
+					//过滤出匹配到的数据
+					var arr = list.filter((e) => {
+						return e[field] == fieldList[j];
+					})
+					att.push({
+						nameType: arr[0].nameType,
+						list: arr
+					})
+				}
+				return att;
+			},
+			selectCity(item,type) {
+				if(type === 'refresh' && !this.hasLocation){
+					// 获取定位
+					return this.getLocation()
+				}
+				// console.log('选择的城市:', item);
+				uni.setStorageSync('myCityObj', item)
+				this.$emit('selectCity', item)
+				// 当前项目是需要选择到区域,所以选择城市后回到区县的地方
+				this.toIndex = 'area';
+				setTimeout(() => {
+					this.toIndex = '';
+				}, 1000);
+			},
+			closeModal(){
+				this.$emit('closeModal')
+			},
+			//列表滚动,和右边字母表对应
+			scrollHandle(e) {
+				let view = uni.createSelectorQuery().in(this).selectAll('.list-item');
+				view
+					.boundingClientRect((d) => {
+						let top = d[0].top;
+						d.forEach((item) => {
+							item.top = item.top - top;
+							item.bottom = item.bottom - top;
+							this.letterDetails.push({
+								id: item.id,
+								top: item.top,
+								bottom: item.bottom,
+							});
+						});
+					})
+					.exec();
+
+				const scrollTop = e.detail.scrollTop;
+				this.letterDetails.some((item) => {
+					if (scrollTop >= item.top && scrollTop <= item.bottom - 20) {
+						this.currentLetter = item.id;
+						//当前固定用的是粘性定位,如果不用粘性定位,在这里设置
+						return true;
+					}
+				});
+			},
+
+			//搜索
+			searchChange(e) {
+				let {
+					value
+				} = e.detail;
+				this.inputValue = value;
+			},
+			// 触发开始
+			touchStart(e) {
+				// console.log(e);
+			},
+			//移动时
+			touchMove(e) {
+				uni.vibrateShort();
+				let y = e.touches[0].clientY;
+				let offsettop = e.currentTarget.offsetTop;
+
+				//判断选择区域,只在选择区才会生效
+				if (y > offsettop) {
+					let num = parseInt((y - offsettop) / 15); //右边每个字母元素的高度
+					let letter = this.alphabet[num];
+					this.tipsLetter = letter;
+
+					let curentLetter = this.letterTransform(letter);
+					uni.showToast({
+						title: curentLetter,
+						icon: 'none',
+					});
+				}
+			},
+			//触发结束
+			touchEnd() {
+				this.toIndex = this.tipsLetter;
+			},
+			//移动开始获取字母,并放大提示
+			getLetter(e) {
+				uni.vibrateShort();
+				let {
+					id
+				} = e.currentTarget;
+				this.tipsLetter = id;
+
+				let curentLetter = this.letterTransform(id);
+				uni.showToast({
+					title: curentLetter,
+					icon: 'none',
+				});
+			},
+			//移动结束设置字母,赋值到toIndex
+			setLetter() {
+				this.toIndex = this.tipsLetter;
+			},
+
+			//提示字母转换
+			letterTransform(letter) {
+				let str = '';
+				if (letter == 'area') {
+					str = '当前';
+				} else if (letter == 'record') {
+					str = '历史';
+				} else {
+					str = letter;
+				}
+				return str;
+			},
+		},
+	}
+</script>
+
+<style lang="less" scoped>
+	.chose-city {
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		z-index: 999;
+		background: #fff;
+	}
+
+	.city-search-wrap {
+		width: 100%;
+		box-sizing: border-box;
+
+		.search {
+			width: 750rpx;
+			height: 110rpx;
+			display: flex;
+			align-items: center;
+			font-size: 28rpx;
+			color: #222;
+			padding: 14rpx 36rpx;
+			box-sizing: border-box;
+			background: #fff;
+
+			.l-search {
+				width: 597rpx;
+				position: relative;
+				height: 72rpx;
+				line-height: 72rpx;
+
+				.icon-search {
+					font-size: 28rpx;
+					position: absolute;
+					left: 30rpx;
+					top: 0;
+					color: #8e8f97;
+					font-weight: 700;
+					height: 72rpx;
+					line-height: 72rpx;
+				}
+				.input-search {
+					width: 597rpx;
+					height: 72rpx;
+					box-sizing: border-box;
+					padding: 0 84rpx 0 84rpx;
+					text-align: left;
+					background: #f4f5f9;
+					border-radius: 12rpx;
+					border: 0;
+				}
+
+				.clear-input {
+					font-size: 30rpx;
+					position: absolute;
+					right: 10rpx;
+					top: 50%;
+					transform: translateY(-50%);
+					padding: 10rpx;
+					color: #8e8f97;
+				}
+			}
+
+			.r-cancel {
+				width: 80rpx;
+				box-sizing: border-box;
+				padding-left: 24rpx;
+				font-size: 28rpx;
+				height: 72rpx;
+				line-height: 72rpx;
+				background: transparent;
+				border: 0;
+				color: #519AD2;
+			}
+		}
+	}
+
+	.reach-content {
+		padding-left: 36rpx;
+		box-sizing: border-box;
+		.li {
+			width: 714rpx;
+			font-size: 28rpx;
+			height: 100rpx;
+			line-height: 100rpx;
+			color: #333;
+			position: relative;
+			box-sizing: border-box;
+			border-bottom: 2rpx solid #F5F5F5;
+		}
+	}
+
+	.block {
+		padding: 0 36rpx;
+		box-sizing: border-box;
+	}
+
+	.top-search {
+		line-height: 72rpx;
+		padding: 14rpx 30rpx 0;
+		box-sizing: border-box;
+		margin-bottom: 26rpx;
+
+		.item {
+			background: #F5F5F5;
+			border-radius: 12rpx;
+			font-size: 28rpx;
+			text-align: center;
+			color: #999999;
+			/* #ifdef MP-ALIPAY */
+			height: 72rpx;
+			line-height: 72rpx;
+
+			/* #endif */
+			text {
+				padding-left: 20rpx;
+				color: #c1c2cd;
+				vertical-align: middle;
+				position: relative;
+				top: -4rpx;
+			}
+
+		}
+	}
+
+	.scroll-view {
+		width: 100%;
+		height: calc(100vh - 110rpx);
+		box-sizing: border-box;
+	}
+
+	.area {
+		margin-bottom: 8rpx;
+
+		.title-wrapp {
+			position: sticky;
+			top: 0;
+			left: 0;
+			background: #fff;
+		}
+
+		.c-title {
+			width: 100%;
+			box-sizing: border-box;
+			font-size: 28rpx;
+			color: #999999;
+			margin-bottom: 24rpx;
+			display: inline-flex;
+			justify-content: space-between;
+			align-items: center;
+
+			.r {
+				font-size: 24rpx;
+				color: #8e8f97;
+				display: inline-block;
+				align-items: center;
+
+				.iconfont {
+					font-size: 24rpx;
+				}
+			}
+		}
+
+		.ul {
+			display: flex;
+			flex-wrap: wrap;
+
+			.li {
+				width: 155rpx;
+				padding: 0 10rpx;
+				box-sizing: border-box;
+				height: 72rpx;
+				line-height: 68rpx;
+				text-align: center;
+				font-size: 32rpx;
+				color: #333;
+				border-radius: 8rpx;
+				margin: 0 18rpx 28rpx 0;
+				border: 2rpx solid #E2E2E2;
+
+				&:nth-child(4n) {
+					margin-right: 0;
+				}
+
+				&.now {
+					width: auto;
+					padding: 0 32rpx 0 22rpx;
+
+					.icon {
+						width: 50rpx;
+						height: 50rpx;
+						background-size: 100%;
+						vertical-align: middle;
+						position: relative;
+						top: -4rpx;
+					}
+
+					.text {
+						padding-left: 10rpx;
+					}
+				}
+
+				&.active {
+					font-weight: 500;
+					background: #ffde45;
+				}
+			}
+
+			.hover {
+				background: #ffde45;
+			}
+		}
+	}
+
+	.city-list {
+		width: 750rpx;
+		padding-bottom: 50rpx;
+
+		.c-title {
+			height: 60rpx;
+			line-height: 60rpx;
+			font-size: 30rpx;
+			font-weight: 500;
+			color: #272636;
+			background: #fff;
+			box-sizing: border-box;
+			padding-left: 36rpx;
+			position: sticky;
+			top: 0;
+			left: 0;
+			z-index: 2;
+		}
+
+		.item {
+			width: 714rpx;
+			margin-left: 36rpx;
+			padding: 0 36rpx 0 0;
+			height: 100rpx;
+			line-height: 100rpx;
+			color: #333;
+			font-size: 28rpx;
+			box-sizing: border-box;
+			border-bottom: 2rpx solid #F5F5F5;
+		}
+	}
+
+	.alphabet {
+		position: fixed;
+		right: 0;
+		bottom: 20%;
+		width: calc(750rpx - 680rpx);
+		text-align: center;
+		font-size: 20rpx;
+		font-weight: 700;
+		color: #8e8f97;
+		z-index: 99;
+
+		.item {
+			height: 15px;
+			line-height: 15px;
+		}
+
+		.active {
+			color: #222;
+		}
+	}
+
+	.has-no-data {
+		font-size: 24rpx;
+		text-align: center;
+		color: #8e8f97;
+		margin-top: 50rpx;
+	}
+	.nav{
+		height: 44px;
+		line-height: 44px;
+		text-align: center;
+		font-size: 26rpx;
+		color:#3C3C3C;
+		position: relative;
+	}
+	.foback{
+		position: absolute;
+		width: 15px;
+		height: 15px;
+		left: 24rpx;
+		top: 15px;
+	}
+</style>

+ 47 - 0
operatingCompany/components/nodata/nodata.vue

@@ -0,0 +1,47 @@
+<template>
+	<view class="" style="padding-bottom: 20rpx;">
+		
+		<view  class="nodataBox">
+			<image src="../../static/img/nodata.png" mode="widthFix" class="nodataImg"></image>
+			<view class="noTxt">暂无数据</view>
+		</view>
+		
+		
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			
+		}
+	},
+	onLoad(opt) {
+      
+	},
+	onShow() {
+		
+	},
+	methods: {
+		
+	}
+}
+</script>
+
+<style scoped>
+	
+	.nodataImg{
+	  width: 400rpx;
+	  padding-top: 100rpx;
+	}
+	.noTxt{
+		font-size: 36rpx;
+		color: #999999;
+		padding-top: 50rpx;
+	}
+	.nodataBox{
+		text-align: center;
+	}
+	
+</style>

+ 429 - 0
operatingCompany/components/timeChose/timeChose.vue

@@ -0,0 +1,429 @@
+<template>
+	<view>
+		<uni-popup ref="popcash" type="bottom" @change="popChange">
+			<view class="pop_phone pop-container">
+				<view class="popup-title">
+					<view class="u-popup-cancel-btn" @click="closepop">取消</view>
+					<view class="u-title" @click="reset">重置</view>
+					<view class="u-popup-sure-btn" @click="handleSelectSure">确定</view>
+				</view>
+				<view class="m-select-time">
+					<view @click="timeChose(0)" class="u-time-label" :style="{ color: timeIndex == 0 ? '#f00' : '#666' }">{{ startTimeDisplay }}</view>
+					<view @click="timeChose(1)" class="u-time-label" :style="{ color: timeIndex == 1 ? '#f00' : '#666' }">{{ endTimeDisplay }}</view>
+				</view>
+				<view class="picker-height">
+					<picker-view v-if="visible" class="mpvue-picker-view" :indicator-style="indicatorStyle" :value.async="curData" @change="bindChange">
+						<picker-view-column>
+							<view class="item" v-for="(item, index) in years" :key="index">{{ item }}年</view>
+						</picker-view-column>
+						<picker-view-column>
+							<view class="item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
+						</picker-view-column>
+						<picker-view-column>
+							<view class="item" v-for="(item, index) in days" :key="index">{{ item }}日</view>
+						</picker-view-column>
+					</picker-view>
+				</view>
+			</view>
+		</uni-popup>
+	</view>
+</template>
+
+<script>
+	//import uniPopup from './uni-popup/uni-popup.vue';
+	export default {
+		/* components: {
+			uniPopup
+		}, */
+		props: {
+			isShow: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			const currentDate = this.getDate({
+				format: true
+			});
+
+
+			const date = new Date();
+			const years = [];
+			const year = date.getFullYear();
+			const months = [];
+			const month = date.getMonth() + 1;
+			const days = [];
+			const day = date.getDate();
+			for (let i = 1990; i <= date.getFullYear(); i++) {
+				years.push(i);
+			}
+			for (let i = 1; i <= 12; i++) {
+				months.push(i);
+			}
+			for (let i = 1; i <= 31; i++) {
+				days.push(i);
+			}
+			return {
+				startTime: '',
+				endTime: '',
+				startTimeDisplay: '开始时间',
+				endTimeDisplay: '结束时间',
+				timeSelectActive: 1,
+				currentDate: '',
+				date: currentDate,
+				timeIndex: 0,
+
+				years,
+				year,
+				months,
+				month,
+				days,
+				day,
+				curData: [9999, month - 1, day - 1],
+				visible: false,
+				indicatorStyle: `height: ${Math.round(uni.getSystemInfoSync().screenWidth / (750 / 100))}px;`
+			};
+		},
+		watch: {
+			isShow(val) {
+				console.log('---val-----', val);
+				this.$refs.popcash.open();
+			}
+		},
+		mounted() {
+			this.startTimeDisplay = this.getTodayTime();
+			this.endTimeDisplay = this.getTodayTime();
+			// this.startDate = this.getDate('start');
+			// this.endDate = this.getDate('end');
+			//this.$refs.popcash.open();
+			this.visible = true;
+			this.timeChose(0);
+
+		},
+		computed: {
+
+		},
+		methods: {
+			//今天的时间
+			getTodayTime() {
+				var day2 = new Date();
+				day2.setTime(day2.getTime());
+				var time = day2.getFullYear() + '-' + this.check0((day2.getMonth() + 1)) + '-' + this.check0(day2.getDate());
+				return time;
+			},
+			check0(num){
+				num = +num;
+				return num > 9 ? num : ('0'+num);
+			},
+			bindChange(e) {
+				const val = e.detail.value;
+				this.curData = val;
+				this.year = this.years[val[0]];
+				this.month = this.months[val[1]];
+				this.day = this.days[val[2]];
+
+				//将选择的年月日变为number形式,便于比较之用
+				var y = parseInt(this.year);
+				var m = parseInt(this.month);
+				var d = parseInt(this.day);
+
+				//选择不同月份显示的天数不同
+				if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) {
+					if (this.days.length != 31) {
+						this.days = [];
+						for (let i = 1; i <= 31; i++) {
+							this.days.push(i);
+						}
+					}
+				} else if (m == 4 || m == 6 || m == 9 || m == 11) {
+					if (this.days.length != 30) {
+						this.days = [];
+						for (let i = 1; i <= 30; i++) {
+							this.days.push(i);
+						}
+					}
+				} else if (m == 2) {
+					if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) {
+						//闰年
+						if (this.days.length != 29) {
+							this.days = [];
+							for (let i = 1; i <= 29; i++) {
+								this.days.push(i);
+							}
+						}
+					} else {
+						//平年
+						if (this.days.length != 28) {
+							this.days = [];
+							for (let i = 1; i <= 28; i++) {
+								this.days.push(i);
+							}
+						}
+					}
+				}
+
+				//处理选择今年的情况
+				if (y == this.currentYear) {
+					//最多显示到当前月份
+					if (this.months.length != this.currentMonth) {
+						this.months = [];
+						for (let i = 1; i <= this.currentMonth; i++) {
+							this.months.push(i);
+						}
+					}
+
+					//如果选择的是当前月份,那么日最多显示到今天
+					if (m == this.currentMonth) {
+						if (this.days.length != this.currentDay) {
+							this.days = [];
+							for (let i = 1; i <= this.currentDay; i++) {
+								this.days.push(i);
+							}
+						}
+					}
+				} else {
+					this.months = [];
+					for (let i = 1; i <= 12; i++) {
+						this.months.push(i);
+					}
+				}
+
+				//我的业务中是选择的孩子日期,根据选择的日期可以计算出孩子几岁了😄
+				if (y >= this.currentYear) {
+					this.babyAge = 0;
+				} else {
+					//选择的月份大于当前月份
+					if (m > this.currentMonth) {
+						this.babyAge = this.currentYear - y - 1;
+					} else if (m == this.currentMonth) {
+						if (d > this.currentDay) {
+							this.babyAge = this.currentYear - y - 1;
+						} else {
+							this.babyAge = this.currentYear - y;
+						}
+					} else {
+						this.babyAge = this.currentYear - y;
+					}
+				}
+				
+				this.month = this.check0(this.month);
+				this.day = this.check0(this.day);
+				
+				if (this.timeIndex == 0) {
+					this.startTimeDisplay = this.year.toString() + '-' + this.month.toString() + '-' + this.day.toString();
+				} else {
+					this.endTimeDisplay = this.year.toString() + '-' + this.month.toString() + '-' + this.day.toString()
+				}
+				console.log('当前选中' + this.year.toString() + '-' + this.month.toString() + '-' + this.day.toString());
+			},
+			timeChose(index) {
+				var that = this;
+				this.timeIndex = index;
+				// this.curData = [0,0,0];
+				var date = index === 0 ? this.startTimeDisplay : this.endTimeDisplay;
+				that.curData = that.getCurIndex(date);
+				console.log(this.curData)
+			},
+			getCurIndex(date) {
+				var years = +date.split('-')[0];
+				var months = +date.split('-')[1];
+				var days = +date.split('-')[2];
+
+				return [this.years.indexOf(years), this.months.indexOf(months), this.days.indexOf(days)]
+			},
+			popChange(e) {
+				console.log('----popChange---', e);
+				/* if (!e.show) {
+					var obj = {
+						isclose: true
+					};
+					this.$emit('returnDate', obj);
+				} */
+			},
+			closepop() {
+				this.$refs.popcash.close();
+			},
+			dateMinus(date1, date2) {
+				var sdate = new Date(date1.replace(/-/g, "/"));
+				var now = new Date(date2.replace(/-/g, "/"));
+				var days = now.getTime() - sdate.getTime();
+				var day = parseInt(days / (1000 * 60 * 60 * 24));
+				return day;
+			},
+			startDateChange: function(e) {
+				this.timeIndex = 0;
+				this.startTimeDisplay = e.target.value;
+			},
+			endDateChange: function(e) {
+				this.timeIndex = 1;
+				this.endTimeDisplay = e.target.value;
+			},
+			getDate(type) {
+				const date = new Date();
+				let year = date.getFullYear();
+				let month = date.getMonth() + 1;
+				let day = date.getDate();
+
+				if (type === 'start') {
+					year = year - 50;
+				} else if (type === 'end') {
+					year = year + 2;
+				}
+				month = month > 9 ? month : '0' + month;
+				day = day > 9 ? day : '0' + day;
+				return `${year}-${month}-${day}`;
+			},
+			handleSetActive(active) {
+				this.timeSelectActive = active;
+
+				let time;
+				if (active === 1) {
+					time = this.startTimeDisplay.split('-');
+				} else {
+					time = this.endTimeDisplay.split('-');
+				}
+
+				this.currentDate = new Date(time[0], +time[1] - 1, time[2]);
+			},
+			timeSelectInput(evt) {
+				if (this.timeSelectActive == 1) {
+					this.startTimeDisplay = evt.getValues().join('-');
+				} else if (this.timeSelectActive == 2) {
+					this.endTimeDisplay = evt.getValues().join('-');
+				}
+			},
+			handleSelectSure() {
+				if (this.startTimeDisplay == '开始时间') {
+					uni.showToast({
+						title: '请选择开始时间',
+						icon: 'none'
+					});
+					return;
+				}
+				if (this.endTimeDisplay == '结束时间') {
+					uni.showToast({
+						title: '请选择结束时间',
+						icon: 'none'
+					});
+					return;
+				}
+				var start = this.startTimeDisplay.split('-');
+				var end = this.endTimeDisplay.split('-');
+				var totalDay = 0;
+				/* if (new Date(start[0], +start[1] - 1, start[2]) > new Date(end[0], +end[1] - 1, end[2])) {
+					this.startTime = this.endTimeDisplay;
+					this.endTime = this.startTimeDisplay;
+					totalDay = this.dateMinus(this.endTimeDisplay, this.startTimeDisplay);
+				} else {
+					this.startTime = this.startTimeDisplay;
+					this.endTime = this.endTimeDisplay;
+					totalDay = this.dateMinus(this.startTimeDisplay, this.endTimeDisplay);
+				} */
+				this.startTime = this.startTimeDisplay;
+				this.endTime = this.endTimeDisplay;
+				console.log(this.startTime, this.endTime)
+				
+				// if (+totalDay > 31) {
+				// 	uni.showToast({
+				// 		title: '最多可查询31天内的数据',
+				// 		icon: 'none'
+				// 	});
+				// 	return;
+				// }
+				
+				var obj = {
+					startTime: this.startTime,
+					endTime: this.endTime,
+					isclose: false
+				};
+				this.$emit('returnDate', obj);
+				this.$refs.popcash.close();
+				//this.isShow=false;
+			},
+			reset(){
+				var obj = {
+					startTime: 0,
+					endTime: 0,
+					isclose: false
+				};
+				this.$emit('returnDate', obj);
+				this.$refs.popcash.close();
+			},
+			 father(){
+				 this.$refs.popcash.open();
+			 }
+		}
+	};
+</script>
+
+<style scoped lang="scss">
+	.pop-container {
+		height: 700upx;
+		background: #fff;
+	}
+
+	.picker-height {
+		height: 400upx;
+	}
+
+	.popup-title {
+		height: 90rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+	}
+
+	.u-title {
+		font-size: 30rpx;
+	}
+
+	.u-popup-cancel-btn {
+		color: #999;
+		padding: 0 30rpx;
+		height: 90rpx;
+		line-height: 90rpx;
+	}
+
+	.u-popup-sure-btn {
+		color: #007aff;
+		padding: 0 30rpx;
+		height: 90rpx;
+		line-height: 90rpx;
+	}
+
+	.m-select-time {
+		height: 160rpx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		font-size: 34rpx;
+	}
+
+	.u-time-label {
+		color: #ccc;
+		width: 220rpx;
+		height: 60rpx;
+		line-height: 60rpx;
+		border-bottom: 1px solid #ccc;
+		text-align: center;
+		margin: 0 40rpx;
+	}
+
+	.mpvue-picker-view {
+		width: 100%;
+		height: 100%;
+		// height: 280upx;
+		background-color: rgba(255, 255, 255, 1);
+
+		.item {
+			text-align: center;
+			width: 100%;
+			height: 100upx;
+			line-height: 100upx;
+			text-overflow: ellipsis;
+			white-space: nowrap;
+			font-size: 30upx;
+		}
+	}
+</style>
+

+ 85 - 5
operatingCompany/pages/entryReport/entered.vue

@@ -22,32 +22,63 @@
 			<view class="topLine" style="border: none;">
 				<view class="topLineTitle">访问人</view>
 				<view class="topLineRIght">
-					<span class="topSpan">这是门店名称</span>
+					<span class="topSpan">{{ShopName}}</span>
+				</view>
+			</view>
+		</view>
+		
+		<view class="kbox" v-for="(v,i) in list">
+			<view class="kboxTitle">{{v.categoryName}}</view>
+			<view class="kboxLineCont">
+				<view class="kline" v-for="(item,index) in v.sectionList">
+					<image src="../../static/img/icon_luru@2x.png" mode="" class="klineImg"></image>
+					<view class="klineName">{{item.checkName}}</view>
 				</view>
 			</view>
 		</view>
-	</view>
 		
-	  
+	</view>
+	
+	  <view style="height: 150rpx;"></view>
+	  <view class="bottom">
+		  <view class="bottomBtn">完成,填写下一步行动建议</view>
+	  </view>
 	   
 	</view>
 </template>
 
 <script>
+	
 	export default {
+		
 		data() {
 			return {
 				userInfo:'',
 				date:'',
 				nowDate:'',
+				shopId:'',
+				ShopName:'',
+				list:'',
 			}
 		},
-		onLoad() {
+		onLoad(opt) {
           //页面加载初始化生命周期函数
 		   this.userInfo=uni.getStorageSync("userInfo");
-		   this.getTime()
+		   this.ShopName=opt.ShopName;
+		   this.shopId=opt.shopId;
+		   this.getTime();
+		   this.getCheckPackageInfo();
+		   
 		},
 		methods: {
+			getCheckPackageInfo(){
+				this.$http('accompany/SuperCheckSheet/queryCheckPackageInfo', {
+					shopID:this.shopId
+				}, 'GET').then(res => {
+					this.list=res.data.categoryList;
+					
+				})
+			},
 			bindTimeChange(e){
 				console.log(e);
 				this.date=e.detail.value
@@ -112,6 +143,7 @@
 	}
 	.top{
 		background: #FFFFFF;
+		border-radius: 10rpx;
 	}
 	.topLine{
 		font-size: 28rpx;
@@ -137,4 +169,52 @@
 	.topTime{
 		width: 400rpx;
 	}
+	.klineImg{
+		width: 70rpx;height: 70rpx;
+	}
+	.kbox{
+		background: #FFFFFF;
+		margin-top: 20rpx;
+	}
+	.kboxTitle{
+		font-size:32rpx;
+		font-weight: 600;
+		color: #3C3C3C;
+		padding: 30rpx 20rpx;
+	}
+	.kboxLineCont{
+		display: flex;
+		flex-wrap: wrap;
+		padding-bottom: 20rpx;
+	}
+	.kline{
+		width: 25%;
+		text-align: center;
+		padding: 20rpx 0;
+	}
+	.klineName{
+		color: #3C3C3C;
+		line-height: 36rpx;
+	}
+	.bottom{
+		width: 750rpx;
+		height: 120rpx;
+		background: #FFFFFF;
+		box-shadow: 0px -4px 8px 0px rgba(153,153,153,0.08);
+		position: fixed;
+		left: 0;
+		bottom: 0;
+	}
+	.bottomBtn{
+		width: 702rpx;
+		height: 74rpx;
+		background: linear-gradient(124deg, #FF8700 0%, #FF4F00 100%);
+		border-radius: 37rpx;
+		text-align: center;
+		line-height: 74rpx;
+		color: #FFFFFF;
+		font-size:30rpx;
+		margin-top: 24rpx;
+		margin-left: 24rpx;
+	}
 </style>

+ 12 - 3
operatingCompany/pages/entryReport/entryReport.vue

@@ -74,7 +74,7 @@
 					<view class="btns">
 						<view class="lishi">历史记录</view>
 						<view class="qiandao">签到</view>
-						<view class="baogao" @click="goEntered()">录入报告</view>
+						<view class="baogao" @click="goEntered(item)">录入报告</view>
 					</view>
 				</view>
 			</view>
@@ -117,13 +117,22 @@
 					
 					that.page = 1
 					 that.getShopData()
+				},
+				fail() {
+				
 				}
 			})
+			  //#ifdef H5 
+			  
+			  that.lng='117.06533'
+			  that.lat='36.68013'
+			  that.getShopData()
+			   // #endif
 		},
 		methods: {
-			goEntered(){
+			goEntered(item){
 				uni.navigateTo({
-					url:'entered'
+					url:'entered?shopId='+item.shopId+'&ShopName='+item.ShopName
 				})
 			},
 			searchDone(e) {

+ 56 - 16
operatingCompany/pages/reportManage/reportManage.vue

@@ -26,14 +26,15 @@
 			<!-- 条件筛选 -->
 			<view class="siftBg">
 				<!-- 日期选择 -->
-				<picker @change="timeChose" mode="date">
-					<view class="uni-input">{{data.value == null ? '日期筛选' : data.value}}
+				<!-- <picker @change="timeChose" mode="date">
+					<view class="uni-input">
 						<image class="downArrow" src="../../static/img/icon_downArrow.png"></image>
 					</view>
 				</picker>
-
+ -->           
+                <view @click="timeClick">{{data.time == null ? '日期筛选' : data.time}}</view>
 				<!-- 省市区 选择 -->
-				<picker @change="bindChange" mode="region">
+				<picker @change="bindChange" mode="region" custom-item="全部">
 					<view class="uni-input">{{data.address == null ? '区域筛选' : data.address}}
 						<image class="downArrow" src="../../static/img/icon_downArrow.png"></image>
 					</view>
@@ -47,7 +48,6 @@
 				</picker>
 			</view>
 		</view>
-
 		<!-- 列表 -->
 		<view class="shopList">
 			<view v-for="(item,index) in shopData" :key="index">
@@ -90,12 +90,16 @@
 			<view class="noTxt">暂无数据</view>
 		</view>
 
-
+      <timeChose ref="timepop" @returnDate="returnDate" :isShow="timeShow"></timeChose>
 	</view>
 </template>
 
 <script>
+	import timeChose from '@/components/timeChose/timeChose.vue'	
 	export default {
+		components: {
+			   timeChose
+		},
 		data() {
 			return {
 				tabIndex: 0,
@@ -109,14 +113,17 @@
 					areaCode: '',
 					area: '',
 					address: null,
+					time:null,
 				},
 				thirdIndex: null,
-				thirdArr: [],
+				thirdArr: [{
+					name:'请选择',ID:''
+				}],
 				managerId: '',
 				shopData: [],
 				page: 1,
 				noMoreShow: false,
-
+                timeShow:false,
 			}
 		},
 		onShow() {
@@ -125,6 +132,21 @@
 			this.getShopData()
 		},
 		methods: {
+			timeClick(){
+				/* this.timeShow=true;
+				console.log(this.timeShow) */
+				this.$refs.timepop.father();
+			},
+			returnDate(e){
+				console.log(e)
+				if(e.startTime){
+					this.data.time=e.startTime+'-'+e.endTime 
+				}else{
+					this.data.time=null
+				}
+				
+				console.log()
+			},
 			tabClick(num) {
 				this.tabIndex = num;
 
@@ -145,13 +167,31 @@
 				
 			},
 			bindChange: function(e) {
-				this.data.provinceCode = e.detail.code[0]
-				this.data.cityCode = e.detail.code[1]
-				this.data.areaCode = e.detail.code[2]
-				this.data.province = e.detail.value[0]
-				this.data.city = e.detail.value[1]
-				this.data.area = e.detail.value[2]
-				this.data.address = this.data.province + this.data.city + this.data.area
+				console.log(e)
+				this.data.address = '区域筛选';
+				this.data.provinceCode='';
+				this.data.cityCode='';
+				this.data.areaCode=''
+				if(e.detail.code[0]){
+					this.data.provinceCode = e.detail.code[0];
+					this.data.province = e.detail.value[0];
+					if( e.detail.code[1]){
+						this.data.cityCode = e.detail.code[1];
+						this.data.city = e.detail.value[1]
+						if(e.detail.code[2]){
+							this.data.areaCode = e.detail.code[2];
+							this.data.area = e.detail.value[2]
+						}
+					}
+					this.data.address = this.data.province + this.data.city + this.data.area
+				}else{
+					
+				}
+				
+				
+				
+				
+				
 				this.page = 1
 				this.getShopData()
 			},
@@ -171,7 +211,7 @@
 						name: '',
 					}
 				this.$http(url, params, 'GET').then(res => {
-					this.thirdArr = res.data
+					this.thirdArr =this.thirdArr.concat(res.data) 
 				})
 			},
 			getShopData() {

BIN
operatingCompany/static/img/baiheiback.png


BIN
operatingCompany/static/img/icon_luru@2x.png


BIN
operatingCompany/static/img/icon_luruhou@2x.png


BIN
operatingCompany/static/img/jiantou.png


+ 37 - 0
operatingCompany/uni_modules/uni-popup/changelog.md

@@ -0,0 +1,37 @@
+## 1.6.2(2021-08-24)
+- 新增 支持国际化
+## 1.6.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.6.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.5.0(2021-06-23)
+- 新增 mask-click 遮罩层点击事件
+## 1.4.5(2021-06-22)
+- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
+## 1.4.4(2021-06-18)
+- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
+## 1.4.3(2021-06-08)
+- 修复 错误的 watch 字段
+- 修复 safeArea 属性不生效的问题
+- 修复 点击内容,再点击遮罩无法关闭的Bug
+## 1.4.2(2021-05-12)
+- 新增 组件示例地址
+## 1.4.1(2021-04-29)
+- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
+## 1.4.0 (2021-04-29)
+- 新增 type 属性的 left\right 值,支持左右弹出
+- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
+- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
+- 新增 safeArea 属性,是否适配底部安全区
+- 修复 App\h5\微信小程序底部安全区占位不对的Bug
+- 修复 App 端弹出等待的Bug
+- 优化 提升低配设备性能,优化动画卡顿问题
+- 优化 更简单的组件自定义方式
+## 1.2.9(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.2.8(2021-02-05)
+- 调整为uni_modules目录规范
+## 1.2.7(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 支持 PC 端
+- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端

+ 45 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js

@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    this.$once('hook:beforeDestroy', () => {
+      document.removeEventListener('keyup', listener)
+    })
+  },
+	render: () => {}
+}
+// #endif

+ 263 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue

@@ -0,0 +1,263 @@
+<template>
+	<view class="uni-popup-dialog">
+		<view class="uni-dialog-title">
+			<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
+		</view>
+		<view v-if="mode === 'base'" class="uni-dialog-content">
+			<slot>
+				<text class="uni-dialog-content-text">{{content}}</text>
+			</slot>
+		</view>
+		<view v-else class="uni-dialog-content">
+			<slot>
+				<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" >
+			</slot>
+		</view>
+		<view class="uni-dialog-button-group">
+			<view class="uni-dialog-button" @click="closeDialog">
+				<text class="uni-dialog-button-text">{{cancelText}}</text>
+			</view>
+			<view class="uni-dialog-button uni-border-left" @click="onOk">
+				<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	import popup from '../uni-popup/popup.js'
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from '../uni-popup/i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	/**
+	 * PopUp 弹出层-对话框样式
+	 * @description 弹出层-对话框样式
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} value input 模式下的默认值
+	 * @property {String} placeholder input 模式下输入提示
+	 * @property {String} type = [success|warning|info|error] 主题样式
+	 *  @value success 成功
+	 * 	@value warning 提示
+	 * 	@value info 消息
+	 * 	@value error 错误
+	 * @property {String} mode = [base|input] 模式、
+	 * 	@value base 基础对话框
+	 * 	@value input 可输入对话框
+	 * @property {String} content 对话框内容
+	 * @property {Boolean} beforeClose 是否拦截取消事件
+	 * @event {Function} confirm 点击确认按钮触发
+	 * @event {Function} close 点击取消按钮触发
+	 */
+
+	export default {
+		name: "uniPopupDialog",
+		mixins: [popup],
+		emits:['confirm','close'],
+		props: {
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			placeholder: {
+				type: [String, Number],
+				default: ''
+			},
+			type: {
+				type: String,
+				default: 'error'
+			},
+			mode: {
+				type: String,
+				default: 'base'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			content: {
+				type: String,
+				default: ''
+			},
+			beforeClose: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				dialogType: 'error',
+				focus: false,
+				val: ""
+			}
+		},
+		computed: {
+			okText() {
+				return t("uni-popup.ok")
+			},
+			cancelText() {
+				return t("uni-popup.cancel")
+			},
+			placeholderText() {
+				return this.placeholder || t("uni-popup.placeholder")
+			},
+			titleText() {
+				return this.title || t("uni-popup.title")
+			}
+		},
+		watch: {
+			type(val) {
+				this.dialogType = val
+			},
+			mode(val) {
+				if (val === 'input') {
+					this.dialogType = 'info'
+				}
+			},
+			value(val) {
+				this.val = val
+			}
+		},
+		created() {
+			// 对话框遮罩不可点击
+			this.popup.disableMask()
+			// this.popup.closeMask()
+			if (this.mode === 'input') {
+				this.dialogType = 'info'
+				this.val = this.value
+			} else {
+				this.dialogType = this.type
+			}
+		},
+		mounted() {
+			this.focus = true
+		},
+		methods: {
+			/**
+			 * 点击确认按钮
+			 */
+			onOk() {
+				if (this.mode === 'input'){
+					this.$emit('confirm', this.val)
+				}else{
+					this.$emit('confirm')
+				}
+				if(this.beforeClose) return
+				this.popup.close()
+			},
+			/**
+			 * 点击取消按钮
+			 */
+			closeDialog() {
+				this.$emit('close')
+				if(this.beforeClose) return
+				this.popup.close()
+			},
+			close(){
+				this.popup.close()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.uni-popup-dialog {
+		width: 300px;
+		border-radius: 15px;
+		background-color: #fff;
+	}
+
+	.uni-dialog-title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		padding-top: 15px;
+		padding-bottom: 5px;
+	}
+
+	.uni-dialog-title-text {
+		font-size: 16px;
+		font-weight: 500;
+	}
+
+	.uni-dialog-content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		padding: 5px 15px 15px 15px;
+	}
+
+	.uni-dialog-content-text {
+		font-size: 14px;
+		color: #6e6e6e;
+	}
+
+	.uni-dialog-button-group {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		border-top-color: #f5f5f5;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-dialog-button {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 45px;
+	}
+
+	.uni-border-left {
+		border-left-color: #f0f0f0;
+		border-left-style: solid;
+		border-left-width: 1px;
+	}
+
+	.uni-dialog-button-text {
+		font-size: 14px;
+	}
+
+	.uni-button-color {
+		color: #007aff;
+	}
+
+	.uni-dialog-input {
+		flex: 1;
+		font-size: 14px;
+		border: 1px #eee solid;
+		height: 40px;
+		padding: 0 10px;
+		border-radius: 5px;
+		color: #555;
+	}
+
+	.uni-popup__success {
+		color: #4cd964;
+	}
+
+	.uni-popup__warn {
+		color: #f0ad4e;
+	}
+
+	.uni-popup__error {
+		color: #dd524d;
+	}
+
+	.uni-popup__info {
+		color: #909399;
+	}
+</style>

+ 143 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue

@@ -0,0 +1,143 @@
+<template>
+	<view class="uni-popup-message">
+		<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
+			<slot>
+				<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
+			</slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	import popup from '../uni-popup/popup.js'
+	/**
+	 * PopUp 弹出层-消息提示
+	 * @description 弹出层-消息提示
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [success|warning|info|error] 主题样式
+	 *  @value success 成功
+	 * 	@value warning 提示
+	 * 	@value info 消息
+	 * 	@value error 错误
+	 * @property {String} message 消息提示文字
+	 * @property {String} duration 显示时间,设置为 0 则不会自动关闭
+	 */
+
+	export default {
+		name: 'uniPopupMessage',
+		mixins:[popup],
+		props: {
+			/**
+			 * 主题 success/warning/info/error	  默认 success
+			 */
+			type: {
+				type: String,
+				default: 'success'
+			},
+			/**
+			 * 消息文字
+			 */
+			message: {
+				type: String,
+				default: ''
+			},
+			/**
+			 * 显示时间,设置为 0 则不会自动关闭
+			 */
+			duration: {
+				type: Number,
+				default: 3000
+			},
+			maskShow:{
+				type:Boolean,
+				default:false
+			}
+		},
+		data() {
+			return {}
+		},
+		created() {
+			this.popup.maskShow = this.maskShow
+			this.popup.messageChild = this
+		},
+		methods: {
+			timerClose(){
+				if(this.duration === 0) return
+				clearTimeout(this.timer) 
+				this.timer = setTimeout(()=>{
+					this.popup.close()
+				},this.duration)
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup-message {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+	}
+
+	.uni-popup-message__box {
+		background-color: #e1f3d8;
+		padding: 10px 15px;
+		border-color: #eee;
+		border-style: solid;
+		border-width: 1px;
+		flex: 1;
+	}
+
+	@media screen and (min-width: 500px) {
+		.fixforpc-width {
+			margin-top: 20px;
+			border-radius: 4px;
+			flex: none;
+			min-width: 380px;
+			/* #ifndef APP-NVUE */
+			max-width: 50%;
+			/* #endif */
+			/* #ifdef APP-NVUE */
+			max-width: 500px;
+			/* #endif */
+		}
+	}
+
+	.uni-popup-message-text {
+		font-size: 14px;
+		padding: 0;
+	}
+
+	.uni-popup__success {
+		background-color: #e1f3d8;
+	}
+
+	.uni-popup__success-text {
+		color: #67C23A;
+	}
+
+	.uni-popup__warn {
+		background-color: #faecd8;
+	}
+
+	.uni-popup__warn-text {
+		color: #E6A23C;
+	}
+
+	.uni-popup__error {
+		background-color: #fde2e2;
+	}
+
+	.uni-popup__error-text {
+		color: #F56C6C;
+	}
+
+	.uni-popup__info {
+		background-color: #F2F6FC;
+	}
+
+	.uni-popup__info-text {
+		color: #909399;
+	}
+</style>

+ 185 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue

@@ -0,0 +1,185 @@
+<template>
+	<view class="uni-popup-share">
+		<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
+		<view class="uni-share-content">
+			<view class="uni-share-content-box">
+				<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
+					<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
+					<text class="uni-share-text">{{item.text}}</text>
+				</view>
+
+			</view>
+		</view>
+		<view class="uni-share-button-box">
+			<button class="uni-share-button" @click="close">{{cancelText}}</button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import popup from '../uni-popup/popup.js'
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from '../uni-popup/i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	export default {
+		name: 'UniPopupShare',
+		mixins:[popup],
+		emits:['select'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			beforeClose: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				bottomData: [{
+						text: '微信',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
+						name: 'wx'
+					},
+					{
+						text: '支付宝',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
+						name: 'wx'
+					},
+					{
+						text: 'QQ',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
+						name: 'qq'
+					},
+					{
+						text: '新浪',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
+						name: 'sina'
+					},
+					{
+						text: '百度',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
+						name: 'copy'
+					},
+					{
+						text: '其他',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
+						name: 'more'
+					}
+				]
+			}
+		},
+		created() {},
+		computed: {
+			cancelText() {
+				return t("uni-popup.cancel")
+			},
+		shareTitleText() {
+				return this.title || t("uni-popup.shareTitle")
+			}
+		},
+		methods: {
+			/**
+			 * 选择内容
+			 */
+			select(item, index) {
+				this.$emit('select', {
+					item,
+					index
+				})
+				this.close()
+
+			},
+			/**
+			 * 关闭窗口
+			 */
+			close() {
+				if(this.beforeClose) return
+				this.popup.close()
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup-share {
+		background-color: #fff;
+	}
+	.uni-share-title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		height: 40px;
+	}
+	.uni-share-title-text {
+		font-size: 14px;
+		color: #666;
+	}
+	.uni-share-content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		padding-top: 10px;
+	}
+
+	.uni-share-content-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: wrap;
+		width: 360px;
+	}
+
+	.uni-share-content-item {
+		width: 90px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		padding: 10px 0;
+		align-items: center;
+	}
+
+	.uni-share-content-item:active {
+		background-color: #f5f5f5;
+	}
+
+	.uni-share-image {
+		width: 30px;
+		height: 30px;
+	}
+
+	.uni-share-text {
+		margin-top: 10px;
+		font-size: 14px;
+		color: #3B4144;
+	}
+
+	.uni-share-button-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: 10px 15px;
+	}
+
+	.uni-share-button {
+		flex: 1;
+		border-radius: 50px;
+		color: #666;
+		font-size: 16px;
+	}
+
+	.uni-share-button::after {
+		border-radius: 50px;
+	}
+</style>

+ 7 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/en.json

@@ -0,0 +1,7 @@
+{
+	"uni-popup.cancel": "cancel",
+	"uni-popup.ok": "ok",
+	"uni-popup.placeholder": "pleace enter",
+	"uni-popup.title": "Hint",
+	"uni-popup.shareTitle": "Share to"
+}

+ 8 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/index.js

@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}

+ 7 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json

@@ -0,0 +1,7 @@
+{
+	"uni-popup.cancel": "取消",
+	"uni-popup.ok": "确定",
+	"uni-popup.placeholder": "请输入",
+		"uni-popup.title": "提示",
+		"uni-popup.shareTitle": "分享到"
+}

+ 7 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json

@@ -0,0 +1,7 @@
+{
+	"uni-popup.cancel": "取消",
+	"uni-popup.ok": "確定",
+	"uni-popup.placeholder": "請輸入",
+	"uni-popup.title": "提示",
+	"uni-popup.shareTitle": "分享到"
+}

+ 45 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/keypress.js

@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    // this.$once('hook:beforeDestroy', () => {
+    //   document.removeEventListener('keyup', listener)
+    // })
+  },
+	render: () => {}
+}
+// #endif

+ 26 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/popup.js

@@ -0,0 +1,26 @@
+
+export default {
+	data() {
+		return {
+			
+		}
+	},
+	created(){
+		this.popup = this.getParent()
+	},
+	methods:{
+		/**
+		 * 获取父元素实例
+		 */
+		getParent(name = 'uniPopup') {
+			let parent = this.$parent;
+			let parentName = parent.$options.name;
+			while (parentName !== name) {
+				parent = parent.$parent;
+				if (!parent) return false
+				parentName = parent.$options.name;
+			}
+			return parent;
+		},
+	}
+}

+ 403 - 0
operatingCompany/uni_modules/uni-popup/components/uni-popup/uni-popup.vue

@@ -0,0 +1,403 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']" @touchmove.stop.prevent="clear">
+		<view @touchstart="touchstart" >
+			<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
+			<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
+				<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear"><slot /></view>
+			</uni-transition>
+		</view>
+		<!-- #ifdef H5 -->
+		<keypress v-if="maskShow" @esc="onTap" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+// #ifdef H5
+import keypress from './keypress.js'
+// #endif
+
+/**
+ * PopUp 弹出层
+ * @description 弹出层组件,为了解决遮罩弹层的问题
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+ * @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
+ * 	@value top 顶部弹出
+ * 	@value center 中间弹出
+ * 	@value bottom 底部弹出
+ * 	@value left		左侧弹出
+ * 	@value right  右侧弹出
+ * 	@value message 消息提示
+ * 	@value dialog 对话框
+ * 	@value share 底部分享示例
+ * @property {Boolean} animation = [ture|false] 是否开启动画
+ * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
+ * @property {String}  backgroundColor 					主窗口背景色
+ * @property {Boolean} safeArea									是否适配底部安全区
+ * @event {Function} change 打开关闭弹窗触发,e={show: false}
+ * @event {Function} maskClick 点击遮罩触发
+ */
+
+export default {
+	name: 'uniPopup',
+	components: {
+		// #ifdef H5
+		keypress
+		// #endif
+	},
+	emits:['change','maskClick'],
+	props: {
+		// 开启动画
+		animation: {
+			type: Boolean,
+			default: true
+		},
+		// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+		// message: 消息提示 ; dialog : 对话框
+		type: {
+			type: String,
+			default: 'center'
+		},
+		// maskClick
+		maskClick: {
+			type: Boolean,
+			default: true
+		},
+		backgroundColor: {
+			type: String,
+			default: 'none'
+		},
+		safeArea:{
+			type: Boolean,
+			default: true
+		}
+	},
+
+	watch: {
+		/**
+		 * 监听type类型
+		 */
+		type: {
+			handler: function(type) {
+				if (!this.config[type]) return
+				this[this.config[type]](true)
+			},
+			immediate: true
+		},
+		isDesktop: {
+			handler: function(newVal) {
+				if (!this.config[newVal]) return
+				this[this.config[this.type]](true)
+			},
+			immediate: true
+		},
+		/**
+		 * 监听遮罩是否可点击
+		 * @param {Object} val
+		 */
+		maskClick: {
+			handler: function(val) {
+				this.mkclick = val
+			},
+			immediate: true
+		}
+	},
+	data() {
+		return {
+			duration: 300,
+			ani: [],
+			showPopup: false,
+			showTrans: false,
+			popupWidth: 0,
+			popupHeight: 0,
+			config: {
+				top: 'top',
+				bottom: 'bottom',
+				center: 'center',
+				left: 'left',
+				right: 'right',
+				message: 'top',
+				dialog: 'center',
+				share: 'bottom'
+			},
+			maskClass: {
+				position: 'fixed',
+				bottom: 0,
+				top: 0,
+				left: 0,
+				right: 0,
+				backgroundColor: 'rgba(0, 0, 0, 0.4)'
+			},
+			transClass: {
+				position: 'fixed',
+				left: 0,
+				right: 0
+			},
+			maskShow: true,
+			mkclick: true,
+			popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
+		}
+	},
+	computed: {
+		isDesktop() {
+			return this.popupWidth >= 500 && this.popupHeight >= 500
+		},
+		bg() {
+			if (this.backgroundColor === '' || this.backgroundColor === 'none') {
+				return 'transparent'
+			}
+			return this.backgroundColor
+		}
+	},
+	mounted() {
+		const fixSize = () => {
+			const { windowWidth, windowHeight, windowTop, safeAreaInsets } = uni.getSystemInfoSync()
+			this.popupWidth = windowWidth
+			this.popupHeight = windowHeight + windowTop
+			// 是否适配底部安全区
+			if(this.safeArea){
+				this.safeAreaInsets = safeAreaInsets
+			}else{
+				this.safeAreaInsets = 0
+			}
+		}
+		fixSize()
+		// #ifdef H5
+		// window.addEventListener('resize', fixSize)
+		// this.$once('hook:beforeDestroy', () => {
+		// 	window.removeEventListener('resize', fixSize)
+		// })
+		// #endif
+	},
+	created() {
+		this.mkclick = this.maskClick
+		if (this.animation) {
+			this.duration = 300
+		} else {
+			this.duration = 0
+		}
+		// TODO 处理 message 组件生命周期异常的问题
+		this.messageChild = null
+		// TODO 解决头条冒泡的问题
+		this.clearPropagation = false
+	},
+	methods: {
+		/**
+		 * 公用方法,不显示遮罩层
+		 */
+		closeMask() {
+			this.maskShow = false
+		},
+		/**
+		 * 公用方法,遮罩层禁止点击
+		 */
+		disableMask() {
+			this.mkclick = false
+		},
+		// TODO nvue 取消冒泡
+		clear(e) {
+			// #ifndef APP-NVUE
+			e.stopPropagation()
+			// #endif
+			this.clearPropagation = true
+		},
+
+		open(direction) {
+			let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
+			if (!(direction && innerType.indexOf(direction) !== -1)) {
+				direction = this.type
+			}
+			if (!this.config[direction]) {
+				console.error('缺少类型:', direction)
+				return
+			}
+			this[this.config[direction]]()
+			this.$emit('change', {
+				show: true,
+				type: direction
+			})
+		},
+		close(type) {
+			this.showTrans = false
+			this.$emit('change', {
+				show: false,
+				type: this.type
+			})
+			clearTimeout(this.timer)
+			// // 自定义关闭事件
+			// this.customOpen && this.customClose()
+			this.timer = setTimeout(() => {
+				this.showPopup = false
+			}, 300)
+		},
+		// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
+		touchstart(){
+			this.clearPropagation = false
+		},
+
+		onTap() {
+			if (this.clearPropagation) {
+				// fix by mehaotian 兼容 nvue
+				this.clearPropagation = false
+				return
+			}
+			this.$emit('maskClick')
+			if (!this.mkclick) return
+			this.close()
+		},
+		/**
+		 * 顶部弹出样式处理
+		 */
+		top(type) {
+			this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
+			this.ani = ['slide-top']
+			this.transClass = {
+				position: 'fixed',
+				left: 0,
+				right: 0,
+				backgroundColor: this.bg
+			}
+			// TODO 兼容 type 属性 ,后续会废弃
+			if (type) return
+			this.showPopup = true
+			this.showTrans = true
+			this.$nextTick(() => {
+				if (this.messageChild && this.type === 'message') {
+					this.messageChild.timerClose()
+				}
+			})
+		},
+		/**
+		 * 底部弹出样式处理
+		 */
+		bottom(type) {
+			this.popupstyle = 'bottom'
+			this.ani = ['slide-bottom']
+
+			this.transClass = {
+				position: 'fixed',
+				left: 0,
+				right: 0,
+				bottom: 0,
+				paddingBottom: (this.safeAreaInsets && this.safeAreaInsets.bottom) || 0,
+				backgroundColor: this.bg
+			}
+			// TODO 兼容 type 属性 ,后续会废弃
+			if (type) return
+			this.showPopup = true
+			this.showTrans = true
+		},
+		/**
+		 * 中间弹出样式处理
+		 */
+		center(type) {
+			this.popupstyle = 'center'
+			this.ani = ['zoom-out', 'fade']
+			this.transClass = {
+				position: 'fixed',
+				/* #ifndef APP-NVUE */
+				display: 'flex',
+				flexDirection: 'column',
+				/* #endif */
+				bottom: 0,
+				left: 0,
+				right: 0,
+				top: 0,
+				justifyContent: 'center',
+				alignItems: 'center'
+			}
+			// TODO 兼容 type 属性 ,后续会废弃
+			if (type) return
+			this.showPopup = true
+			this.showTrans = true
+		},
+		left(type) {
+			this.popupstyle = 'left'
+			this.ani = ['slide-left']
+			this.transClass = {
+				position: 'fixed',
+				left: 0,
+				bottom: 0,
+				top: 0,
+				backgroundColor: this.bg,
+				/* #ifndef APP-NVUE */
+				display: 'flex',
+				flexDirection: 'column'
+				/* #endif */
+			}
+			// TODO 兼容 type 属性 ,后续会废弃
+			if (type) return
+			this.showPopup = true
+			this.showTrans = true
+		},
+		right(type) {
+			this.popupstyle = 'right'
+			this.ani = ['slide-right']
+			this.transClass = {
+				position: 'fixed',
+				bottom: 0,
+				right: 0,
+				top: 0,
+				backgroundColor: this.bg,
+				/* #ifndef APP-NVUE */
+				display: 'flex',
+				flexDirection: 'column'
+				/* #endif */
+			}
+			// TODO 兼容 type 属性 ,后续会废弃
+			if (type) return
+			this.showPopup = true
+			this.showTrans = true
+		}
+	}
+}
+</script>
+<style lang="scss" scoped>
+.uni-popup {
+	position: fixed;
+	/* #ifndef APP-NVUE */
+	z-index: 99;
+	/* #endif */
+	&.top,
+	&.left,
+	&.right {
+		/* #ifdef H5 */
+		top: var(--window-top);
+		/* #endif */
+		/* #ifndef H5 */
+		top: 0;
+		/* #endif */
+	}
+	.uni-popup__wrapper {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: relative;
+		/* iphonex 等安全区设置,底部安全区适配 */
+		/* #ifndef APP-NVUE */
+		// padding-bottom: constant(safe-area-inset-bottom);
+		// padding-bottom: env(safe-area-inset-bottom);
+		/* #endif */
+		&.left,
+		&.right {
+			/* #ifdef H5 */
+			padding-top: var(--window-top);
+			/* #endif */
+			/* #ifndef H5 */
+			padding-top: 0;
+			/* #endif */
+			flex: 1;
+		}
+	}
+}
+
+.fixforpc-z-index {
+	/* #ifndef APP-NVUE */
+	z-index: 999;
+	/* #endif */
+}
+
+.fixforpc-top {
+	top: 0;
+}
+</style>

+ 89 - 0
operatingCompany/uni_modules/uni-popup/package.json

@@ -0,0 +1,89 @@
+{
+	"id": "uni-popup",
+	"displayName": "uni-popup 弹出层",
+	"version": "1.6.2",
+	"description": " Popup 组件,提供常用的弹层",
+	"keywords": [
+        "uni-ui",
+        "弹出层",
+        "弹窗",
+        "popup",
+        "弹框"
+    ],
+	"repository": "https://github.com/dcloudio/uni-ui",
+	"engines": {
+		"HBuilderX": ""
+	},
+	"directories": {
+		"example": "../../temps/example_temps"
+	},
+	"dcloudext": {
+		"category": [
+			"前端组件",
+			"通用组件"
+		],
+		"sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+		"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+	},
+	"uni_modules": {
+		"dependencies": [
+			"uni-transition"
+		],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+				"aliyun": "y"
+			},
+			"client": {
+				"App": {
+					"app-vue": "y",
+					"app-nvue": "y"
+				},
+				"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"
+				},
+				"快应用": {
+					"华为": "u",
+					"联盟": "u"
+                },
+                "Vue": {
+                    "vue2": "y",
+                    "vue3": "u"
+                }
+			}
+		}
+	}
+}

+ 296 - 0
operatingCompany/uni_modules/uni-popup/readme.md

@@ -0,0 +1,296 @@
+
+
+## Popup 弹出层
+> **组件名:uni-popup**
+> 代码块: `uPopup`
+> 关联组件:`uni-popup-dialog`,`uni-popup-message`,`uni-popup-share`,`uni-transition`
+
+
+弹出层组件,在应用中弹出一个消息提示窗口、提示框等
+
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - `uni-popup-message` 、 `uni-popup-dialog` 等扩展ui组件,需要和 `uni-popup` 配套使用,暂不支持单独使用
+> - `nvue` 中使用 `uni-popup` 时,尽量将组件置于其他元素后面,避免出现层级问题
+> - `uni-popup` 并不能完全阻止页面滚动,可在打开 `uni-popup` 的时候手动去做一些处理,禁止页面滚动
+> - 如果想在页面渲染完毕后就打开 `uni-popup` ,请在 `onReady` 或 `mounted` 生命周期内调用,确保组件渲染完毕
+> - 在微信小程序开发者工具中,启用真机调试,popup 会延时出现,是因为 setTimeout 在真机调试中的延时问题导致的,预览和发布小程序不会出现此问题
+> - 使用 `npm` 方式引入组件,如果确认引用正确,但是提示未注册组件或显示不正常,请尝试重新编译项目
+> - `uni-popup` 中尽量不要使用 `scroll-view` 嵌套过多的内容,可能会影响组件的性能,导致组件无法打开或者打开卡顿
+> - `uni-popup` 不会覆盖原生 tabbar 和原生导航栏
+> - 组件支持 nvue ,需要在 `manifest.json > app-plus` 节点下配置 `"nvueStyleCompiler" : "uni-app"` 
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+
+### 基本用法 
+
+**示例**
+
+```html
+<button @click="open">打开弹窗</button>
+<uni-popup ref="popup" type="bottom">底部弹出 Popup</uni-popup>
+```
+
+```javascript
+export default {
+   methods:{
+      open(){
+        // 通过组件定义的ref调用uni-popup方法 ,如果传入参数 ,type 属性将失效 ,仅支持 ['top','left','bottom','right','center']
+        this.$refs.popup.open('top')
+      }
+   }
+}
+
+```
+
+### 设置主窗口背景色
+
+在大多数场景下,并不需要设置 `background-color` 属性,因为`uni-popup`的主窗口默认是透明的,在向里面插入内容的时候 ,样式完全交由用户定制,如果设置了背景色 ,例如 `uni-popup-dialog` 中的圆角就很难去实现,不设置背景色,更适合用户去自由发挥。
+
+而也有特例,需要我们主动去设置背景色,例如 `type = 'bottom'` 的时候 ,在异型屏中遇到了底部安全区问题(如 iphone 11),因为 `uni-popup`的主要内容避开了安全区(设置`safe-area:true`),导致底部的颜色我们无法自定义,这时候使用 `background-color` 就可以解决这个问题。 
+
+**示例**
+
+```html
+<button @click="open">打开弹窗</button>
+<uni-popup ref="popup" type="bottom" background-color="#fff">底部弹出 Popup</uni-popup>
+```
+
+### 禁用打开动画
+在某些场景 ,可能不希望弹层有动画效果 ,只需要将 `animation` 属性设置为 `false` 即可以关闭动画。
+
+**示例**
+
+```html
+<button @click="open">打开弹窗</button>
+<uni-popup ref="popup" type="center" :animation="false">中间弹出 Popup</uni-popup>
+```
+
+### 禁用点击遮罩关闭
+默认情况下,点击遮罩会自动关闭`uni-popup`,如不想点击关闭,只需将`mask-click`设置为`false`,这时候要关闭`uni-popup`,只能手动调用 `close` 方法。
+
+**示例**
+
+```html
+<button @click="open">打开弹窗</button>
+<uni-popup ref="popup" :mask-click="false">
+	<text>Popup</text>
+	<button @click="close">关闭</button>
+</uni-popup>
+```
+
+```javascript
+export default {
+	data() {
+		return {}
+	},
+	onReady() {},
+	methods: {
+		open() {
+			this.$refs.popup.open('top')
+		},
+		close() {
+			this.$refs.popup.close()
+		}
+	}
+}
+
+```
+
+## API
+
+### Popup Props 
+
+|属性名|类型|默认值|说明|
+|:-:|:-:|:-:|:-:|
+|animation|Boolean|true|是否开启动画|
+|type|String|'center'|弹出方式|
+|mask-click|Boolean|true|蒙版点击是否关闭弹窗|
+|background-color|String|'none'|主窗口背景色|
+|safe-area|Boolean|true|是否适配底部安全区|
+
+#### Type Options
+
+|属性名|说明|
+|:-:| :-:|
+|top|顶部弹出	|
+|center|居中弹出|
+|bottom|底部弹出|
+|left|左侧弹出|
+|right|右侧弹出|
+|message|预置样式 :消息提示|
+|dialog|预置样式 :对话框|
+|share|预置样式 :底部弹出分享示例	|
+
+
+### Popup Methods
+
+|方法称名	|说明|参数|
+|:-:|:-:|:-:|
+|open|打开弹出层|open(String:type) ,如果参数可代替 type 属性|
+|close|关闭弹出层	|-|
+
+
+### Popup Events
+
+|事件称名|说明|返回值|
+|:-:|:-:|:-:|
+|change|组件状态发生变化触发|e={show: true|false,type:当前模式}|
+|maskClick|点击遮罩层触发|-|
+
+
+## 扩展组件说明
+`uni-popup` 其实并没有任何样式,只提供基础的动画效果,给用户一个弹出层解决方案,仅仅是这样并不能满足开发需求,所以我们提供了三种基础扩展样式
+
+### uni-popup-message 提示信息
+
+将 `uni-popup` 的`type`属性改为 `message`,并引入对应组件即可使用消息提示 ,*该组件不支持单独使用*
+
+**示例**
+
+```html
+<uni-popup ref="popup" type="message">
+	<uni-popup-message type="success" message="成功消息" :duration="2000"></uni-popup-message>
+</uni-popup>
+```
+
+### PopupMessage Props
+
+|属性名|类型|默认值|说明|
+|:-:|:-:|:-:|:-:|
+|type|String|success|消息提示主题|
+|message|String|-|消息提示文字|
+|duration|Number|3000|消息显示时间,超过显示时间组件自动关闭,设置为0 将不会关闭,需手动调用 close 方法关闭|
+
+#### Type Options
+
+|属性名|说明|
+|:-:| :-:|
+|success|成功	|
+|warn|警告|
+|error|失败|
+|info|消息|
+
+### PopupMessage Slots
+
+|名称|说明|					
+|:-:|:-:|						
+|default|消息内容,会覆盖 message 属性|
+
+### uni-popup-dialog 对话框
+
+将 `uni-popup` 的`type`属性改为 `dialog`,并引入对应组件即可使用对话框 ,*该组件不支持单独使用*
+
+**示例**
+
+```html
+<button @click="open">打开弹窗</button>
+<uni-popup ref="popup" type="dialog">
+	<uni-popup-dialog mode="input" message="成功消息" :duration="2000" :before-close="true" @close="close" @confirm="confirm"></uni-popup-dialog>
+</uni-popup>
+```
+
+```javascript
+export default {
+	methods: {
+		open() {
+			this.$refs.popup.open()
+		},
+		/**
+		 * 点击取消按钮触发
+		 * @param {Object} done
+		 */
+		close() {
+			// TODO 做一些其他的事情,before-close 为true的情况下,手动执行 close 才会关闭对话框
+			// ...
+			this.$refs.popup.close()
+		},
+		/**
+		 * 点击确认按钮触发
+		 * @param {Object} done
+		 * @param {Object} value
+		 */
+		confirm(value) {
+			// 输入框的值
+			console.log(value)
+			// TODO 做一些其他的事情,手动执行 close 才会关闭对话框
+			// ...
+			this.$refs.popup.close()
+		}
+	}
+}
+```
+
+### PopupDialog Props
+
+|属性名|类型|默认值|说明|
+|:-:|:-:|:-:|:-:|
+|type|String|success|对话框标题主题,可选值: success/warn/info/error|
+|mode|String|base| 对话框模式,可选值:base(提示对话框)/input(可输入对话框)|
+|title|String|-|对话框标题|
+|content|String|-|对话框内容,base模式下生效|
+|value| String\Number|-|输入框默认值,input模式下生效|
+|placeholder|String|-|输入框提示文字,input模式下生效|
+|before-close|Boolean|false	| 是否拦截按钮事件,如为true,则不会关闭对话框,关闭需要手动执行 uni-popup 的 close 方法|
+
+#### PopupDialog Events
+
+|事件称名	|说明|返回值|
+|:-:|:-:|:-:|
+|close|点击dialog取消按钮触发|-|
+|confirm|点击dialog确定按钮触发|e={value:input模式下输入框的值}|
+
+### PopupDialog Slots
+
+|名称|说明|					
+|:-:|:-:|						
+|default|自定义内容,回覆盖原有的内容显示|
+
+### uni-popup-share 分享示例
+
+分享示例,不作为最终可使用的组件,只做为样式组件,供用户自行修改,`后续的开发计划是实现实际的分享逻辑,参数可配置`。
+
+将 `uni-popup` 的 `type` 属性改为 `share`,并引入对应组件即可使用 ,*该组件不支持单独使用*
+
+**示例**
+
+```html
+<uni-popup ref="popup" type="share">
+	<uni-popup-share title="分享到" @select="select"></uni-popup-share>
+</uni-popup>
+```
+
+### PopupShare Props
+
+|属性名|类型|默认值|说明|
+|:-:|:-:|:-:| :-:			|
+|title|String|-|分享弹窗标题|
+|before-close|Boolean|false	| 是否拦截按钮事件,如为true,则不会关闭对话框,关闭需要手动执行 uni-popup 的 close 方法|
+
+### PopupShare Events
+
+|事件称名|说明|返回值|
+|:-:|:-:|:-:|
+|select|选择触发|e = {item,index}:所选参数|
+
+**Tips**
+- share 分享组件,只是作为一个扩展示例,如果需要修改数据源,请到组件内修改
+
+## 帮助
+在使用中如遇到无法解决的问题,请提 [Issues](https://github.com/dcloudio/uni-ui/issues) 给我们。
+
+
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/popup/popup](https://hellouniapp.dcloud.net.cn/pages/extUI/popup/popup)

+ 13 - 0
operatingCompany/uni_modules/uni-transition/changelog.md

@@ -0,0 +1,13 @@
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.1(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的Bug
+## 1.1.0(2021-04-22)
+- 新增 通过方法自定义动画
+- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式
+- 优化 动画触发逻辑,使动画更流畅
+- 优化 支持单独的动画类型
+- 优化 文档示例
+## 1.0.2(2021-02-05)
+- 调整为uni_modules目录规范

+ 128 - 0
operatingCompany/uni_modules/uni-transition/components/uni-transition/createAnimation.js

@@ -0,0 +1,128 @@
+// const defaultOption = {
+// 	duration: 300,
+// 	timingFunction: 'linear',
+// 	delay: 0,
+// 	transformOrigin: '50% 50% 0'
+// }
+// #ifdef APP-NVUE
+const nvueAnimation = uni.requireNativePlugin('animation')
+// #endif
+class MPAnimation {
+	constructor(options, _this) {
+		this.options = options
+		this.animation = uni.createAnimation(options)
+		this.currentStepAnimates = {}
+		this.next = 0
+		this.$ = _this
+
+	}
+
+	_nvuePushAnimates(type, args) {
+		let aniObj = this.currentStepAnimates[this.next]
+		let styles = {}
+		if (!aniObj) {
+			styles = {
+				styles: {},
+				config: {}
+			}
+		} else {
+			styles = aniObj
+		}
+		if (animateTypes1.includes(type)) {
+			if (!styles.styles.transform) {
+				styles.styles.transform = ''
+			}
+			let unit = ''
+			if(type === 'rotate'){
+				unit = 'deg'
+			}
+			styles.styles.transform += `${type}(${args+unit}) `
+		} else {
+			styles.styles[type] = `${args}`
+		}
+		this.currentStepAnimates[this.next] = styles
+	}
+	_animateRun(styles = {}, config = {}) {
+		let ref = this.$.$refs['ani'].ref
+		if (!ref) return
+		return new Promise((resolve, reject) => {
+			nvueAnimation.transition(ref, {
+				styles,
+				...config
+			}, res => {
+				resolve()
+			})
+		})
+	}
+
+	_nvueNextAnimate(animates, step = 0, fn) {
+		let obj = animates[step]
+		if (obj) {
+			let {
+				styles,
+				config
+			} = obj
+			this._animateRun(styles, config).then(() => {
+				step += 1
+				this._nvueNextAnimate(animates, step, fn)
+			})
+		} else {
+			this.currentStepAnimates = {}
+			typeof fn === 'function' && fn()
+			this.isEnd = true
+		}
+	}
+
+	step(config = {}) {
+		// #ifndef APP-NVUE
+		this.animation.step(config)
+		// #endif
+		// #ifdef APP-NVUE
+		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
+		this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
+		this.next++
+		// #endif
+		return this
+	}
+
+	run(fn) {
+		// #ifndef APP-NVUE
+		this.$.animationData = this.animation.export()
+		this.$.timer = setTimeout(() => {
+			typeof fn === 'function' && fn()
+		}, this.$.durationTime)
+		// #endif
+		// #ifdef APP-NVUE
+		this.isEnd = false
+		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
+		if(!ref) return
+		this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
+		this.next = 0
+		// #endif
+	}
+}
+
+
+const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
+	'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
+	'translateZ'
+]
+const animateTypes2 = ['opacity', 'backgroundColor']
+const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
+animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
+	MPAnimation.prototype[type] = function(...args) {
+		// #ifndef APP-NVUE
+		this.animation[type](...args)
+		// #endif
+		// #ifdef APP-NVUE
+		this._nvuePushAnimates(type, args)
+		// #endif
+		return this
+	}
+})
+
+export function createAnimation(option, _this) {
+	if(!_this) return
+	clearTimeout(_this.timer)
+	return new MPAnimation(option, _this)
+}

+ 277 - 0
operatingCompany/uni_modules/uni-transition/components/uni-transition/uni-transition.vue

@@ -0,0 +1,277 @@
+<template>
+	<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+</template>
+
+<script>
+import { createAnimation } from './createAnimation'
+
+/**
+ * Transition 过渡动画
+ * @description 简单过渡动画组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+ * @property {Boolean} show = [false|true] 控制组件显示或隐藏
+ * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
+ *  @value fade 渐隐渐出过渡
+ *  @value slide-top 由上至下过渡
+ *  @value slide-right 由右至左过渡
+ *  @value slide-bottom 由下至上过渡
+ *  @value slide-left 由左至右过渡
+ *  @value zoom-in 由小到大过渡
+ *  @value zoom-out 由大到小过渡
+ * @property {Number} duration 过渡动画持续时间
+ * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+ */
+export default {
+	name: 'uniTransition',
+	emits:['click','change'],
+	props: {
+		show: {
+			type: Boolean,
+			default: false
+		},
+		modeClass: {
+			type: [Array, String],
+			default() {
+				return 'fade'
+			}
+		},
+		duration: {
+			type: Number,
+			default: 300
+		},
+		styles: {
+			type: Object,
+			default() {
+				return {}
+			}
+		},
+		customClass:{
+			type: String,
+			default: ''
+		}
+	},
+	data() {
+		return {
+			isShow: false,
+			transform: '',
+			opacity: 1,
+			animationData: {},
+			durationTime: 300,
+			config: {}
+		}
+	},
+	watch: {
+		show: {
+			handler(newVal) {
+				if (newVal) {
+					this.open()
+				} else {
+					// 避免上来就执行 close,导致动画错乱
+					if (this.isShow) {
+						this.close()
+					}
+				}
+			},
+			immediate: true
+		}
+	},
+	computed: {
+		// 生成样式数据
+		stylesObject() {
+			let styles = {
+				...this.styles,
+				'transition-duration': this.duration / 1000 + 's'
+			}
+			let transform = ''
+			for (let i in styles) {
+				let line = this.toLine(i)
+				transform += line + ':' + styles[i] + ';'
+			}
+			return transform
+		},
+		// 初始化动画条件
+		transformStyles() {
+			return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
+		}
+	},
+	created() {
+		// 动画默认配置
+		this.config = {
+			duration: this.duration,
+			timingFunction: 'ease',
+			transformOrigin: '50% 50%',
+			delay: 0
+		}
+		this.durationTime = this.duration
+	},
+	methods: {
+		/**
+		 *  ref 触发 初始化动画
+		 */
+		init(obj = {}) {
+			if (obj.duration) {
+				this.durationTime = obj.duration
+			}
+			this.animation = createAnimation(Object.assign(this.config, obj))
+		},
+		/**
+		 * 点击组件触发回调
+		 */
+		onClick() {
+			this.$emit('click', {
+				detail: this.isShow
+			})
+		},
+		/**
+		 * ref 触发 动画分组
+		 * @param {Object} obj
+		 */
+		step(obj, config = {}) {
+			if (!this.animation) return
+			for (let i in obj) {
+				try {
+					if(typeof obj[i] === 'object'){
+						this.animation[i](...obj[i])
+					}else{
+						this.animation[i](obj[i])
+					}
+				} catch (e) {
+					console.error(`方法 ${i} 不存在`)
+				}
+			}
+			this.animation.step(config)
+			return this
+		},
+		/**
+		 *  ref 触发 执行动画
+		 */
+		run(fn) {
+			if (!this.animation) return
+			this.animation.run(fn)
+		},
+		// 开始过度动画
+		open() {
+			clearTimeout(this.timer)
+			this.transform = ''
+			this.isShow = true
+			let { opacity, transform } = this.styleInit(false)
+			if (typeof opacity !== 'undefined') {
+				this.opacity = opacity
+			}
+			this.transform = transform
+			// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
+			this.$nextTick(() => {
+				// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
+				this.timer = setTimeout(() => {
+					this.animation = createAnimation(this.config, this)
+					this.tranfromInit(false).step()
+					this.animation.run()
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				}, 20)
+			})
+		},
+		// 关闭过度动画
+		close(type) {
+			if (!this.animation) return
+			this.tranfromInit(true)
+				.step()
+				.run(() => {
+					this.isShow = false
+					this.animationData = null
+					this.animation = null
+					let { opacity, transform } = this.styleInit(false)
+					this.opacity = opacity || 1
+					this.transform = transform
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				})
+		},
+		// 处理动画开始前的默认样式
+		styleInit(type) {
+			let styles = {
+				transform: ''
+			}
+			let buildStyle = (type, mode) => {
+				if (mode === 'fade') {
+					styles.opacity = this.animationType(type)[mode]
+				} else {
+					styles.transform += this.animationType(type)[mode] + ' '
+				}
+			}
+			if (typeof this.modeClass === 'string') {
+				buildStyle(type, this.modeClass)
+			} else {
+				this.modeClass.forEach(mode => {
+					buildStyle(type, mode)
+				})
+			}
+			return styles
+		},
+		// 处理内置组合动画
+		tranfromInit(type) {
+			let buildTranfrom = (type, mode) => {
+				let aniNum = null
+				if (mode === 'fade') {
+					aniNum = type ? 0 : 1
+				} else {
+					aniNum = type ? '-100%' : '0'
+					if (mode === 'zoom-in') {
+						aniNum = type ? 0.8 : 1
+					}
+					if (mode === 'zoom-out') {
+						aniNum = type ? 1.2 : 1
+					}
+					if (mode === 'slide-right') {
+						aniNum = type ? '100%' : '0'
+					}
+					if (mode === 'slide-bottom') {
+						aniNum = type ? '100%' : '0'
+					}
+				}
+				this.animation[this.animationMode()[mode]](aniNum)
+			}
+			if (typeof this.modeClass === 'string') {
+				buildTranfrom(type, this.modeClass)
+			} else {
+				this.modeClass.forEach(mode => {
+					buildTranfrom(type, mode)
+				})
+			}
+
+			return this.animation
+		},
+		animationType(type) {
+			return {
+				fade: type ? 1 : 0,
+				'slide-top': `translateY(${type ? '0' : '-100%'})`,
+				'slide-right': `translateX(${type ? '0' : '100%'})`,
+				'slide-bottom': `translateY(${type ? '0' : '100%'})`,
+				'slide-left': `translateX(${type ? '0' : '-100%'})`,
+				'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
+				'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
+			}
+		},
+		// 内置动画类型与实际动画对应字典
+		animationMode() {
+			return {
+				fade: 'opacity',
+				'slide-top': 'translateY',
+				'slide-right': 'translateX',
+				'slide-bottom': 'translateY',
+				'slide-left': 'translateX',
+				'zoom-in': 'scale',
+				'zoom-out': 'scale'
+			}
+		},
+		// 驼峰转中横线
+		toLine(name) {
+			return name.replace(/([A-Z])/g, '-$1').toLowerCase()
+		}
+	}
+}
+</script>
+
+<style></style>

+ 83 - 0
operatingCompany/uni_modules/uni-transition/package.json

@@ -0,0 +1,83 @@
+{
+  "id": "uni-transition",
+  "displayName": "uni-transition 过渡动画",
+  "version": "1.2.0",
+  "description": "元素的简单过渡动画",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "动画",
+    "过渡",
+    "过渡动画"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "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"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}

+ 397 - 0
operatingCompany/uni_modules/uni-transition/readme.md

@@ -0,0 +1,397 @@
+
+
+## Transition 过渡动画
+> **组件名:uni-transition**
+> 代码块: `uTransition`
+
+
+元素过渡动画
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - rotate 旋转动画不需要填写 deg 单位,在小程序上填写单位动画不会执行
+> - NVUE 下修改宽高动画,不能定位到中心点
+> - 百度小程序下修改宽高 ,可能会影响其他动画,需注意
+> - nvue 不支持 costom-class , 请使用 styles
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+<template>
+	<view>
+		<button type="primary" @click="open">fade</button>
+		<uni-transition mode-class="fade" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show" @change="change" />
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			show: false,
+		}
+	},
+	onLoad() {},
+	methods: {
+		open(mode) {
+			this.show = !this.show
+		},
+		change() {
+			console.log('触发动画')
+		}
+	}
+}
+</script>
+```
+
+### 样式覆盖
+
+**注意:`nvue` 不支持 `custom-class` 属性 ,需要使用 `styles` 属性进行兼容**
+
+使用 `custom-class` 属性绑定样式,可以自定义 `uni-transition` 的样式
+
+```html
+<template>
+	<view class="content">
+		<uni-transition custom-class="custom-transition" mode-class="fade" :duration="0" :show="true" />
+	</view>
+</template>
+
+<style>
+/* 常规样式覆盖  */
+.content >>> .custom-transition {
+	width:100px;
+	height:100px;
+	background-color:red;
+}
+</style>
+<style lang="scss">
+/* 如果使用 scss 需要使用 /deep/  */
+.content /deep/ .custom-transition {
+	width:100px;
+	height:100px;
+	background-color:red;
+}
+</style>
+```
+
+
+如果使用 `styles` 注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+
+```html
+<template>
+	<view class="content">
+		<uni-transition :styles="styles" mode-class="fade" :duration="0" :show="true" />
+	</view>
+</template>
+<script>
+export default {
+	data() {
+		return {
+			styles:{
+				'width':'100px',
+				'height':'100px',
+				'backgroundColor':'red'
+			}
+		}
+	}
+}
+</script>
+```
+
+### 自定义动画
+当内置动画类型不能满足需求的时候 ,可以使用 `step()` 和 `run()` 自定义动画,入参以及具体用法参考下方属性说明
+
+`init()` 方法可以覆盖默认配置
+
+
+```html
+<template>
+	<view>
+		<button type="primary" @click="run">执行动画</button>
+		<uni-transition ref="ani" :styles="{'width':'100px','height':'100px','backgroundColor':'red'}" :show="show"  />
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			show: true,
+		}
+	},
+	onReady() {
+		this.$refs.ani.init({
+			duration: 1000,
+			timingFunction: 'linear',
+			transformOrigin: '50% 50%',
+			delay: 500
+		})
+	},
+	methods: {
+		run() {
+			// 同时右平移到 100px,旋转 360 读
+			this.$refs.ani.step({
+				translateX: '100px',
+				rotate: '360'
+			})
+			// 上面的动画执行完成后,等待200毫秒平移到 0px,旋转到 0 读
+			this.$refs.ani.step({
+				translateX: '0px',
+				rotate: '0'
+			},
+			{
+				timingFunction: 'ease-in',
+				duration: 200
+			})
+			// 开始执行动画
+			this.$refs.ani.run(()=>{
+				console.log('动画支持完毕')
+			})
+		}
+	}
+}
+</script>
+```
+
+
+## API
+
+### Transition Props
+
+|属性名		|类型	|默认值	|说明					|
+|:-:	|:-:	|:-:					|:-:|
+|show				|Boolean|false	|控制组件显示或隐藏	|
+|mode-class |Array/String	|-		|内置过渡动画类型			|
+|custom-class |String	|-		|自定义类名	|
+|duration	 |Number	|300	|过渡动画持续时间		|
+|styles		 |Object	|-		|组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`	|
+
+#### mode-class 内置过渡动画类型说明
+**格式为** :`'fade'` 或者 `['fade','slide-top']`
+
+|属性名			|说明			|
+|:-:			|:-:			|
+|fade			|渐隐渐出过渡	|
+|slide-top		|由上至下过渡	|
+|slide-right	|由右至左过渡	|
+|slide-bottom	|由下至上过渡	|
+|slide-left		|由左至右过渡	|
+|zoom-in		|由小到大过渡	|
+|zoom-out		|由大到小过渡	|
+
+**注意** 
+
+组合使用时,同一种类型相反的过渡动画如(slide-top、slide-bottom)同时使用时,只有最后一个生效
+
+### Transition Events
+
+|事件名		|说明				|返回值			|
+|:-:			|:-:				|:-:			|
+|click		|点击组件触发		|-				|
+|change		|过渡动画结束时触发	| e = {detail:true}	|
+
+### Transition Methons
+
+|方法名|说明|参数|
+|:-:|:-:|:-:|
+|init()|手动初始化配置|Function(OBJECT:config)|
+|step()|动画队列|Function(OBJECT:type,OBJECT:config)|
+|run()|执行动画|Function(FUNCTION:callback)	|
+
+### init(OBJECT:config)
+**通过 ref 调用方法**
+
+手动设置动画配置,需要在页面渲染完毕后调用
+
+```javascript
+this.$refs.ani.init({
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+```
+
+### step(OBJECT:type,OBJECT:config) 动画队列
+**通过 ref 调用方法**
+
+调用 `step()` 来表示一组动画完成,`step` 第一个参数可以传入任意多个动画方法,一组动画中的所有动画会同时开始,一组动画完成后才会进行下一组动画。`step` 第二个参数可以传入一个跟 `uni.createAnimation()` 一样的配置参数用于指定当前组动画的配置。
+
+Tips
+- 第一个参数支持的动画参考下面的 `支持的动画`
+- 第二个参数参考下面的 `动画配置`,可省略,如果省略继承`init`的配置
+
+
+```javascript
+this.$refs.ani.step({
+	translateX: '100px'
+},{
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+```
+
+### run(FUNCTION:callback) 执行动画
+**通过 ref 调用方法**
+
+在执行 `step()` 后,需要调用 `run()` 来运行动画 ,否则动画会一直等待
+
+`run()` 方法可以传入一个 `callback` 函数 ,会在所有动画执行完毕后回调
+
+```javascript
+this.$refs.ani.step({
+	translateX: '100px'
+})
+this.$refs.ani.run(()=>{
+	console.log('动画执行完毕')
+})
+
+```
+
+### 动画配置
+动画配置 , `init()` 与 `step()` 第二个参数配置相同 ,如果配置`step() `第二个参数,将会覆盖 `init()` 的配置
+
+|属性名|值|必填|默认值|说明|平台差异|
+|:-:|:-:|:-:|:-:|:-:|:-:|
+|duration|Number|否|400|动画持续时间,单位ms|-|
+|timingFunction|String|否|"linear"|定义动画的效果|-|
+|delay|Number|否|0|动画延迟时间,单位 ms|-|
+|needLayout|Boolean|否|false	|动画执行是否影响布局|仅 nvue 支持|
+|transformOrigin|String	|否|"center center"|设置	[transform-origin](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin)|-|
+
+
+### timingFunction 属性说明
+
+|值|说明|平台差异|
+|:-:|:-:|:-:|
+|linear|动画从头到尾的速度是相同的|-|
+|ease|动画以低速开始,然后加快,在结束前变慢|-|
+|ease-in|	动画以低速开始|-|
+|ease-in-out|	动画以低速开始和结束|-|
+|ease-out|动画以低速结束|-|
+|step-start|动画第一帧就跳至结束状态直到结束|nvue不支持|
+|step-end|动画一直保持开始状态,最后一帧跳到结束状态|nvue不支持|
+
+```javascript
+// init 配置
+this.$refs.ani.init({
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+// step 配置
+this.$refs.ani.step({
+	translateX: '100px'
+},{
+	duration: 1000,
+	timingFunction:'ease',
+	delay:500,
+	transformOrigin:'left center'
+})
+```
+
+### 支持的动画
+动画方法 
+
+如果同一个动画方法有多个值,多个值使用数组分隔
+
+```javascript
+this.$refs.ani.step({
+	width:'100px',
+	scale: [1.2,0.8],
+})
+```
+
+**样式:**
+
+|属性名|值|说明|平台差异|
+|:-:|:-:|:-:|:-:|
+|opacity|value|透明度,参数范围 0~1|-|
+|backgroundColor|color|颜色值|-|
+|width|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|-|
+|height|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|-|
+|top|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+|left|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+|bottom|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+|right|length|长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值|nvue 不支持|
+
+```javascript
+this.$refs.ani.step({
+	opacity: 1,
+	backgroundColor: '#ff5a5f',
+	widht:'100px',
+	height:'50rpx',
+})
+```
+
+**旋转:**
+
+旋转属性的值不需要填写单位
+
+|属性名|值|说明|平台差异	|
+|:-:|:-:|:-:|:-:|
+|rotate|deg|deg的范围-180~180,从原点顺时针旋转一个deg角度	|-|
+|rotateX|deg|deg的范围-180~180,在X轴旋转一个deg角度				|-|
+|rotateY|deg|deg的范围-180~180,在Y轴旋转一个deg角度				|-|
+|rotateZ|deg|deg的范围-180~180,在Z轴旋转一个deg角度				|nvue不支持|
+|rotate3d|x,y,z,deg| 同	[transform-function rotate3d](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d())		|nvue不支持|
+
+```javascript
+this.$refs.ani.step({
+	rotateX: 45,
+	rotateY: 45
+})
+```
+
+**缩放:**
+
+|属性名|值|说明|平台差异|
+|:-:|:-:|:-:	|:-:|
+|scale|sx,[sy]|一个参数时,表示在X轴、Y轴同时缩放sx倍数;两个参数时表示在X轴缩放sx倍数,在Y轴缩放sy倍数|-|
+|scaleX|sx|在X轴缩放sx倍数|-|
+|scaleY|sy|在Y轴缩放sy倍数|-|
+|scaleZ|sz|在Z轴缩放sy倍数|nvue不支持|
+|scale3d|sx,sy,sz|在X轴缩放sx倍数,在Y轴缩放sy倍数,在Z轴缩放sz倍数|nvue不支持|
+
+```javascript
+this.$refs.ani.step({
+	scale: [1.2,0.8]
+})
+```
+
+**偏移:**
+
+|属性名|值|说明|平台差异|
+|:-:|:-:|:-:|:-:|
+|translate|tx,[ty]|一个参数时,表示在X轴偏移tx,单位px;两个参数时,表示在X轴偏移tx,在Y轴偏移ty,单位px。|-|
+|translateX|tx|	在X轴偏移tx,单位px|-|
+|translateY|ty|	在Y轴偏移tx,单位px|-|
+|translateZ|tz|	在Z轴偏移tx,单位px|nvue不支持|
+|translate3d|tx,ty,tz|	在X轴偏移tx,在Y轴偏移ty,在Z轴偏移tz,单位px|nvue不支持|
+
+```javascript
+this.$refs.ani.step({
+	translateX: '100px'
+})
+```
+
+
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/transition/transition](https://hellouniapp.dcloud.net.cn/pages/extUI/transition/transition)